J'ai versé sur la description de format et le code source pour le format d'archive 7z, mais j'ai toujours des difficultés à écrire un conteneur valide. Je suppose que je peux créer un conteneur vide ... De toute façon voici mon départ:Comment écrire des données binaires pour le format d'archive 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();
Je pense que mon principal problème est un manque de compréhension de std :: ofstream :: write(). Byte est un 'char non signé', UInt64 & UInt32 sont tous les deux 'unsigned long'.
UPDATE0: Comme tout le monde le fait remarquer, ce serait un problème si je l'exécutais sur une machine big-endian. Ce n'est pas le cas ici. Pour Fredrik Janssen, je devrais jeter l'adresse des non-réseaux. Je devrais également mentionner que CrcCalc() est une fonction dans le SDK LZMA. Ajoutant & aide un peu, c'est ce premier char non signé [6] qui a quelques problèmes.
UPDATE1: Code de travail pour obtenir un fichier d'archive vide ci-dessous.
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();
}
REMARQUE: CrcGenerateTable() et CrcCalc() sont du SDK LZMA.
J'ai juste remarqué le & moi-même. Le format est little-endian et je suis sur un CPU little-endian ... Je vais m'inquiéter de la portabilité plus tard. ;) –
Les ampersands manquants étaient le problème. De plus, j'ai bourré les autres valeurs dans un tableau de tampons, en suivant l'exemple de la source 7z. Merci pour les yeux supplémentaires. –
Juste heureux d'aider :) Bonne chance avec le projet! –