3

7zアーカイブ形式の形式の説明とソースコードを注いでいますが、有効なコンテナを作成するのにまだ問題があります。空のコンテナを作成できると思います...とにかくここから始めます:

std::ofstream ofs(archivename.c_str(), std::ios::binary|std::ios::trunc);

Byte signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
Byte major = 0;
Byte minor = 3;

ofs.write((const char*)signature, 6);
ofs.write((const char*)major, 1);
ofs.write((const char*)minor, 1);

UInt64 offset = 0;
UInt64 size = 0;
UInt32 crc = 0;

ofs.write((const char*)offset, 4);
ofs.write((const char*)size, 8);
ofs.write((const char*)crc, 8);
ofs.write((const char*)CrcCalc(0, 0), 8);

ofs.close();

私の主な問題は、std :: ofstream :: write()の理解不足だと思います。バイトは「unsignedchar」であり、UInt64とUInt32は両方とも「unsignedlong」です。

UPDATE0:誰もが指摘しているように、これをビッグエンディアンのマシンで実行すると問題になります。ここではそうではありません。Fredrik Janssenによると、非配列のアドレスをキャストする必要があります。また、CrcCalc()はLZMASDKの関数であることにも言及する必要があります。&を少し追加すると、いくつかの問題が発生しているのは、最初のunsignedchar[6]です。

UPDATE1:以下の空のアーカイブファイルを取得するための作業コード。

static void SetUInt32(Byte *p, UInt32 d)
{
  for (int i = 0; i < 4; i++, d >>= 8)
    p[i] = (Byte)d;
}

static void SetUInt64(Byte *p, UInt64 d)
{
  for (int i = 0; i < 8; i++, d >>= 8)
    p[i] = (Byte)d;
}

void make_7z_archive()
{
  CrcGenerateTable();

  std::ofstream ofs(archivename.c_str(), std::ios::binary|std::ios::trunc);

  Byte signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
  Byte major = 0;
  Byte minor = 3;

  ofs.write((const char*)signature, 6);
  ofs.write((const char*)&major, 1);
  ofs.write((const char*)&minor, 1);

  UInt64 offset = 0;
  UInt64 size = 0;
  UInt32 crc = 0;

  Byte buf[24];
  SetUInt64(buf + 4, offset);
  SetUInt64(buf + 12, size);
  SetUInt32(buf + 20, crc);
  SetUInt32(buf, CrcCalc(buf + 4, 20));

  ofs.write((const char*)buf, 24);

  ofs.close();
}

注:CrcGenerateTable()およびCrcCalc()は、LZMASDKからのものです。

4

2 に答える 2

2

7zの形式はわかりませんが、オフセット、サイズ、およびcrcを書き留めると、これらがリトルエンディアン形式でファイルに書き込まれることに気付きます(リトルエンディアンCPUを使用していると仮定します)。

編集: おそらくさらに悪いことに、major、minor、offset、size、crc の前に & がありません。つまり、実際の値をポインタにキャストしています。

于 2009-01-30T16:45:16.823 に答える