2012-07-06 11 views
8

Sto cercando di archiviare i file per un'applicazione multipiattaforma, e sembra che Minizip (costruito su zlib) sia portatile quanto gli archivisti.Come utilizzare Minizip (su Zlib)?

Quando provo ad eseguire il seguente codice fittizio, però, ho un errore di sistema [my executable] has stopped working. Windows can check online for a solution to the problem.

qualcuno mi può aiutare a vedere come utilizzare questa libreria? — (non c'è doc o tutorial da nessuna parte che posso trovare)

zip_fileinfo zfi; 

int main() 
{ 
    zipFile zf = zipOpen("myarch.zip",APPEND_STATUS_ADDINZIP); 
    int ret = zipOpenNewFileInZip(zf, 
     "myfile.txt", 
     &zfi, 
     NULL, 0, 
     NULL, 0, 
     "my comment for this interior file", 
     Z_DEFLATED, 
     Z_NO_COMPRESSION 
     ); 
    zipCloseFileInZip(zf); 
    zipClose(zf, "my comment for exterior file"); 
    return 0; 
} 

Spec: Msys + MinGW, Windows 7, utilizzando zlibwapi.dll da zlib125dll.zip/dll32

risposta

16

Poiché ho trovato questa domanda tramite Google e non conteneva alcun codice completo e funzionante, ne fornisco alcuni per i futuri visitatori.

int CreateZipFile (std::vector<wstring> paths) 
{ 
    zipFile zf = zipOpen(std::string(destinationPath.begin(), destinationPath.end()).c_str(), APPEND_STATUS_CREATE); 
    if (zf == NULL) 
     return 1; 

    bool _return = true; 
    for (size_t i = 0; i < paths.size(); i++) 
    { 
     std::fstream file(paths[i].c_str(), std::ios::binary | std::ios::in); 
     if (file.is_open()) 
     { 
      file.seekg(0, std::ios::end); 
      long size = file.tellg(); 
      file.seekg(0, std::ios::beg); 

      std::vector<char> buffer(size); 
      if (size == 0 || file.read(&buffer[0], size)) 
      { 
       zip_fileinfo zfi = { 0 }; 
       std::wstring fileName = paths[i].substr(paths[i].rfind('\\')+1); 

       if (S_OK == zipOpenNewFileInZip(zf, std::string(fileName.begin(), fileName.end()).c_str(), &zfi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION)) 
       { 
        if (zipWriteInFileInZip(zf, size == 0 ? "" : &buffer[0], size)) 
         _return = false; 

        if (zipCloseFileInZip(zf)) 
         _return = false; 

        file.close(); 
        continue; 
       } 
      } 
      file.close(); 
     } 
     _return = false; 
    } 

    if (zipClose(zf, NULL)) 
     return 3; 

    if (!_return) 
     return 4; 
    return S_OK; 
} 
+0

Questo è buono. Alcuni problemi però: 1. Ciò presuppone che l'intero file possa essere contenuto nella memoria, il che è in qualche modo una visione semplicistica, ma forse abbastanza buono per questo esempio. 2. Non c'è motivo per cui un output di file di lunghezza 0 è un errore se la lunghezza del file iniziale è 0. 3. Supponendo che si tratti di un errore, non è necessario eseguire l'operazione ternaria. Ad esempio, se (zipWriteInFileInZip (zf, size == 0? "": & buffer [0], size)) 'può essere scritto come' if (zipWriteInFileInZip (zf, & buffer [0], size)) '. 4. Consiglierei di non utilizzare un prefisso di sottolineatura. So che stai usando una lettera minuscola dopo di essa, ma ... * scrollando le spalle * – Adrian

+0

Il secondo e il terzo punto che hai sollevato sono sbagliati. La dimensione == 0 controllo serve a garantire che il buffer [0] non venga eseguito su lunghezza zero. La logica o l'operazione nell'istruzione if assicura quindi che i file di lunghezza zero vengano scritti correttamente nel file zip e che il ternario successivo sia, ancora una volta, per garantire che il buffer [0] non venga chiamato sulla lunghezza zero. Il codice funziona correttamente e come previsto. – niemiro

+0

Questo è etichettato come C, non C++. –

2

Il lib Minizip è ben documentata. Basta aprire il file zip.h per i dettagli.

Posso dirvi qui, potrebbe essere passato un parametro errato per zipOpen. (APPEND_STATUS_ADDINZIP richiede un file zip esistente!)

Inoltre, controlla se zipOpen restituisce un handle zipFile valido.

+0

Grazie. Ho cambiato il mio secondo argomento in "APPEND_STATUS_CREATE". Non vedo alcun riferimento alla validità in zip.h; per quello, dovrei controllare se il file zip è 'NULL'? – JellicleCat

+0

Inoltre, puoi far luce su cosa si suppone che siano 'extrafield_local' e' extrafield_global'? Non sto trovando alcun esempio o descrizione sufficiente. – JellicleCat

+0

Non ho mai usato extrafield_local e extrafield_global prima. Mi dispiace, non posso aiutare. Se zip.h non contiene documentazione, è possibile scaricare il codice sorgente zlib. Sono sicuro che zip.h in quel pacchetto contiene una buona documentazione. – Rango

3

La libreria di minizip contiene esempi; minizip.c per zippare e miniunz.c per decomprimere. Entrambi sono utilità della riga di comando che mostrano come utilizzare la libreria. Sono un disastro però.

È inoltre necessario riempire zfi zip_fileinfo. Per lo meno si dovrebbe inizializzare la struttura a zero. zfi contiene informazioni sul file che si desidera archiviare utilizzando zipOpenNewFileInZip. La struttura dovrebbe contenere la data e gli attributi di "myfile.txt".

Si consiglia di utilizzare PKWARE Desktop per diagnosticare problemi di zip. Mostra la struttura/proprietà dei file nello ZIP e il file ZIP stesso. Quando ho aperto il myarch.zip mi ha detto che c'erano errori. Ho approfondito le proprietà del file e ho scoperto che gli attributi erano disattivati.

+1

Grazie per l'indagine, ma nell'esempio di codice sopra, non dovresti inizializzare 'zfi' a zero senza specificarlo? È sul mucchio poiché è al di fuori di qualsiasi funzione, giusto? – JellicleCat

+0

Ah sì, hai ragione. Ho appena gettato il codice in una funzione per vedere se ha funzionato. –

+1

Il tuo codice dovrebbe funzionare correttamente allora. Non ho avuto alcun crash di Windows da esso. Potrebbe essere un problema con l'utilizzo della DLL. Hai provato a compilare nella libreria zlib? –