2009-01-30 9 views
3

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.

Répondre

2

Je ne connais pas le format de 7z, mais je remarque quand vous écrivez offset, size et crc que ceux-ci seront écrits dans le fichier au format little-endian (je suppose que vous avez un CPU little-endian). Edit: Probablement pire, il vous manque & avant majeur, mineur, décalage, taille et crc, c'est-à-dire que vous êtes en train de convertir les valeurs réelles en pointeur.

+0

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. ;) –

+0

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. –

+0

Juste heureux d'aider :) Bonne chance avec le projet! –

0

Euh ... Je suis confus. Il a un SDK ... que vous mentionnez dans votre message ... aussi le 7-zip sources are online. voir aussi p7zip sur SourceForge. Je viens de regarder les sources de p7zip et il y a un tas de fichiers qui commencent par "7z" qui semblent faire l'affaire.

Je n'ai pas utilisé le format 7z moi-même (uniquement via l'interface de ligne de commande/GUI), mais pourquoi auriez-vous besoin de manipuler ces choses de bas niveau plutôt que via le SDK? (autre que à cause de la licence LGPL)

+0

Il n'y a pas de bibliothèque pratique pour l'encodage. Il y a une bibliothèque ANSI-C pour le décodage, un codeur/décodeur pré-construit, puis un tas de code CPP pour une application client entière, et une DLL (juste une interface COM). J'ai besoin de relier statiquement, et je n'ai pas envie de comprendre comment construire juste le code dont j'ai besoin. –

+0

Oops, la bibliothèque ANSI-C effectue l'encodage mais ne gère pas le format d'archivage. J'ai téléchargé p7zip ... d'autres exemples de ce code en action! –

Questions connexes