Question

Je me suis plongé dans la description du format et le code source du format d'archive 7z, mais j'ai toujours du mal à écrire un conteneur valide. Je suppose que je peux créer un conteneur vide ... en tout cas voici mon début:

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 problème principal est un manque de compréhension de std :: ofstream :: write (). Octet est un 'caractère non signé', UInt64 & Amp; UInt32 sont tous 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. Selon Fredrik Janssen, je devrais avoir l'adresse des non-tableaux. Je devrais également mentionner que CrcCalc () est une fonction du SDK LZMA. Ajout de & Amp; aide un peu, c'est ce premier caractère non signé [6] qui a quelques problèmes.

UPDATE1 : code de travail pour obtenir un fichier 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 () proviennent du SDK LZMA.

Était-ce utile?

La solution

ne connais pas le format de 7z, mais je remarque que lorsque vous notez offset, size et crc, ils seront écrits dans le fichier au format little-endian (je suppose que vous avez un processeur little-endian).

Edit: An probablement pire, il vous manque le & ampli; avant majeur, mineur, offset, taille et crc, c’est-à-dire que vous transcrivez les valeurs réelles en un pointeur.

Autres conseils

Euh ... je suis confus. Il possède un SDK ... que vous mentionnez dans votre message ... également le Les sources 7-zip sont en ligne . voir aussi p7zip sur SourceForge. Je viens de jeter un coup d’œil sur les sources de p7zip et il y a un tas de fichiers qui commencent par & "; 7z &"; qui ressemblent ils feraient le tour.

Je n'ai pas moi-même utilisé le format 7z par programme (uniquement via l'utilitaire / l'interface graphique de ligne de commande), mais pourquoi devriez-vous gérer ces éléments de bas niveau vous-même plutôt que via le SDK? (autre que par la licence LGPL)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top