2012-07-06 18 views
8

Estoy tratando de archivar archivos para una aplicación multiplataforma, y ​​parece que Minizip (basado en zlib) es tan portátil como los archivadores.¿Cómo uso Minizip (en Zlib)?

Cuando trato de ejecutar el siguiente código ficticio, sin embargo, me sale un error del sistema [my executable] has stopped working. Windows can check online for a solution to the problem.

Puede alguien ayudarme a ver cómo utilizar esta biblioteca? — (no hay documento o un tutorial en cualquier lugar que puedo encontrar)

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; 
} 

Especificaciones: Msys + MinGW, Windows 7, utilizando zlibwapi.dll de zlib125dll.zip/dll32

Respuesta

16

Como encontré esta pregunta a través de Google y no contenía ningún código de trabajo completo, se lo proporciono aquí a futuros visitantes.

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

Esto es bueno. Sin embargo, algunos problemas: 1. Esto supone que todo el archivo puede caber en la memoria, lo cual es una vista simplista, pero tal vez lo suficientemente buena para esta muestra. 2. No hay ninguna razón por la cual un resultado de archivo de 0 longitud sea un error si la longitud inicial del archivo es 0. 3. Suponiendo que se trata de un error, no hay necesidad de la operación ternaria. es decir 'if (zipWriteInFileInZip (zf, size == 0?" ": & buffer [0], size))' se puede escribir como 'if (zipWriteInFileInZip (zf, & buffer [0], size))'. 4. Recomiendo no usar un prefijo de subrayado. Sé que estás usando una letra minúscula después de ella, pero ... * encoge de hombros * – Adrian

+0

El segundo y el tercer punto que planteas son incorrectos. La comprobación de tamaño == 0 es para garantizar que el almacenamiento intermedio [0] no se ejecute en longitud cero. La operación lógica o de operación en la sentencia if asegura que los archivos de longitud cero se escriban correctamente en el archivo zip, y el ternario posterior es, una vez más, para garantizar que no se invoca el buffer [0] en la longitud cero. El código funciona correctamente y como se esperaba. – niemiro

+0

Esto está etiquetado como C, no C++. –

2

El lib minizip es así documentado. Simplemente abra el zip.h para más detalles.

Puedo decirle aquí, es posible que haya pasado un parámetro incorrecto para zipOpen. (¡APPEND_STATUS_ADDINZIP requiere un archivo zip existente!)

Además, compruebe si zipOpen devuelve un identificador válido de zipFile.

+0

Gracias. Cambié mi 2da arg a 'APPEND_STATUS_CREATE'. No veo ninguna referencia a la validez en zip.h; para eso, ¿debería comprobar si el archivo zip es 'NULL'? – JellicleCat

+0

Además, ¿puedes arrojar algo de luz sobre lo que se supone que 'extrafield_local' y' extrafield_global' son? No encuentro ningún ejemplo o descripción suficiente. – JellicleCat

+0

Nunca utilicé extrafield_local y extrafield_global antes. Lo siento, no puedo ayudar. Si su zip.h no contiene documentación, puede descargar el código fuente zlib. Estoy seguro de que zip.h en ese paquete contiene buena documentación. – Rango

3

La biblioteca minizip viene con ejemplos; minizip.c para comprimir y miniunz.c para descomprimir. Ambas son utilidades de línea de comandos que muestran cómo usar la biblioteca. Sin embargo, son un desastre.

También debe completar el zfi zip_fileinfo. Por lo menos debes inicializar la estructura a cero. zfi contiene información sobre el archivo que desea almacenar usando zipOpenNewFileInZip. La estructura debe contener la fecha y los atributos de "myfile.txt".

Recomiendo usar PKWARE Desktop para diagnosticar problemas de zip. Muestra la estructura/propiedades de los archivos en el ZIP y el archivo ZIP en sí. Cuando abrí myarch.zip me dijo que había errores. Profundicé en las propiedades del archivo y encontré que los atributos estaban apagados.

+1

Gracias por la investigación, pero en el ejemplo de código anterior, ¿no se debe inicializar 'zfi' a cero sin que yo lo especifique? Está en el montón porque está fuera de cualquier función, ¿verdad? – JellicleCat

+0

Ah sí, estás en lo cierto. Acabo de lanzar tu código en una función para ver si funcionó. –

+1

Tu código debería funcionar correctamente. No he tenido ningún bloqueo de Windows. Podría ser un problema con el uso de la DLL. ¿Has intentado compilar en la biblioteca de zlib? –