Como faço para escrever dados binários para o formato de arquivo 7z?
Pergunta
Eu tenho derramando sobre a descrição do formato e código fonte para o formato de arquivo 7z, mas eu ainda estou tendo dificuldade para escrever um recipiente válido. Eu suponho eu posso criar um recipiente vazio ... de qualquer forma aqui está o meu começo:
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();
Eu acho que meu principal problema é a falta de compreensão de std :: ofstream :: write (). Byte é um 'char não assinado', UInt64 & UInt32 são ambos 'unsigned long'.
UPDATE0 : como todos os pontos fora, seria um problema se eu corri isso em uma máquina big-endian. Isso não é o caso aqui. Per Fredrik Janssen, eu deveria estar lançando o endereço dos não-matrizes. Gostaria também de mencionar que CrcCalc () é uma função no LZMA SDK. Adicionando & ajuda um pouco, é que o primeiro unsigned char [6] que está tendo alguns problemas.
Update1 :. Código de Trabalho para obter um arquivo vazio abaixo
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();
}
NOTA: CrcGenerateTable () e CrcCalc () são do LZMA SDK
.Solução
não sei o formato 7z, mas eu aviso quando você anote offset, tamanho e CRC que estes serão gravados no arquivo em little-endian formato (I supor que você tem uma CPU little-endian).
Edit:. Um provavelmente pior, você está faltando o & antes de maior, menor, offset, tamanho e CRC, ou seja, você está lançando os valores reais para um ponteiro
Outras dicas
Uh ... Estou confuso. Ele tem um SDK ... que você menciona no seu post ... também o 7-zip fontes são online. ver também p7zip no SourceForge. Eu só olhei para as fontes para p7zip e há um monte de arquivos que começam com "7z" que parecem que faria o truque.
Eu não usei o formato 7z programattically me (apenas através da linha de comando util / GUI) mas por que você precisa para lidar com essas coisas de baixo nível de si mesmo, em vez de através do SDK? (Que não por causa do licenciamento LGPL)