如何为7z存档格式编写二进制数据?

时间:2009-01-30 16:40:43

标签: c++ std 7zip ofstream

我一直在倾注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()的理解。字节是'unsigned char',UInt64& UInt32都是'unsigned long'。

UPDATE0 :正如大家所指出的那样,如果我在大端机器上运行它会有问题。情况并非如此。根据Fredrik Janssen的说法,我应该转换非数组的地址。我还要提一下,CrcCalc()是LZMA SDK中的一个函数。添加&帮助了一下,这是第一个没有签名的char [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()来自LZMA SDK。

2 个答案:

答案 0 :(得分:2)

不知道7z的格式,但我注意到当你写下offset,size和crc这些将以little-endian格式写入文件时(我假设你有一个小端CPU)。 / p>

编辑:可能更糟糕的是,你错过了&amp;在major,minor,offset,size和crc之前,即你将实际值转换为指针。

答案 1 :(得分:0)

呃......我很困惑。它有一个SDK ...你在帖子中提到了......还有7-zip sources are online。另请参阅SourceForge上的p7zip。我只是看了一下p7zip的来源,有一堆文件以“7z”开头,看起来就像他们会做的那样。

我自己没有以编程方式使用7z格式(只是通过命令行util / GUI)但是为什么你需要自己处理那些低级别的东西而不是通过SDK? (除了因为LGPL许可)