#include "JlCompress.h" #include bool JlCompress::copyData(QIODevice &inFile, QIODevice &outFile) { while (!inFile.atEnd()) { char buf[4096]; qint64 readLen = inFile.read(buf, 4096); if (readLen <= 0) return false; if (outFile.write(buf, readLen) != readLen) return false; } return true; } /**OK * Comprime il file fileName, nell'oggetto zip, con il nome fileDest. * * La funzione fallisce se: * * zip==NULL; * * l'oggetto zip e stato aperto in una modalita non compatibile con l'aggiunta di file; * * non e possibile aprire il file d'origine; * * non e possibile creare il file all'interno dell'oggetto zip; * * si e rilevato un errore nella copia dei dati; * * non e stato possibile chiudere il file all'interno dell'oggetto zip; */ bool JlCompress::compressFile(QuaZip* zip, QString fileName, QString fileDest) { // zip: oggetto dove aggiungere il file // fileName: nome del file reale // fileDest: nome del file all'interno del file compresso // Controllo l'apertura dello zip if (!zip) return false; if (zip->getMode()!=QuaZip::mdCreate && zip->getMode()!=QuaZip::mdAppend && zip->getMode()!=QuaZip::mdAdd) return false; // Apro il file originale QFile inFile; inFile.setFileName(fileName); if(!inFile.open(QIODevice::ReadOnly)) return false; // Apro il file risulato QuaZipFile outFile(zip); if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, inFile.fileName()))) return false; // Copio i dati if (!copyData(inFile, outFile) || outFile.getZipError()!=UNZ_OK) { return false; } // Chiudo i file outFile.close(); if (outFile.getZipError()!=UNZ_OK) return false; inFile.close(); return true; } /**OK * Comprime la cartella dir nel file fileCompressed, se recursive e true allora * comprime anche le sotto cartelle. I nomi dei file preceduti dal path creato * togliendo il pat della cartella origDir al path della cartella dir. * Se la funzione fallisce restituisce false e cancella il file che si e tentato * di creare. * * La funzione fallisce se: * * zip==NULL; * * l'oggetto zip e stato aperto in una modalita non compatibile con l'aggiunta di file; * * la cartella dir non esiste; * * la compressione di una sotto cartella fallisce (1); * * la compressione di un file fallisce; * (1) La funzione si richiama in maniera ricorsiva per comprimere le sotto cartelle * dunque gli errori di compressione di una sotto cartella sono gli stessi di questa * funzione. */ bool JlCompress::compressSubDir( QuaZip* parentZip, QString dir, QString parentDir, bool recursive, QSet& added ) { // zip: oggetto dove aggiungere il file // dir: cartella reale corrente // origDir: cartella reale originale // (path(dir)-path(origDir)) = path interno all'oggetto zip // Controllo l'apertura dello zip if (!parentZip ) return false; if ( parentZip->getMode()!=QuaZip::mdCreate && parentZip->getMode()!=QuaZip::mdAppend && parentZip->getMode()!=QuaZip::mdAdd) return false; // Controllo la cartella QDir directory(dir); if (!directory.exists()) return false; // Se comprimo anche le sotto cartelle if (recursive) { // Per ogni sotto cartella QFileInfoList files = directory.entryInfoList(QDir::AllDirs|QDir::NoDotAndDotDot); Q_FOREACH (QFileInfo file, files) { // Comprimo la sotto cartella if(!compressSubDir( parentZip,file.absoluteFilePath(),parentDir,recursive,added)) return false; } } // Per ogni file nella cartella QFileInfoList files = directory.entryInfoList(QDir::Files); QDir origDirectory( parentDir ); Q_FOREACH (QFileInfo file, files) { // Se non e un file o e il file compresso che sto creando if(!file.isFile()||file.absoluteFilePath()==parentZip->getZipName()) continue; // Creo il nome relativo da usare all'interno del file compresso QString filename = origDirectory.relativeFilePath(file.absoluteFilePath()); // Comprimo il file if (!compressFile( parentZip,file.absoluteFilePath(),filename)) return false; added.insert(filename); } return true; } /**OK * Estrae il file fileName, contenuto nell'oggetto zip, con il nome fileDest. * Se la funzione fallisce restituisce false e cancella il file che si e tentato di estrarre. * * La funzione fallisce se: * * zip==NULL; * * l'oggetto zip e stato aperto in una modalita non compatibile con l'estrazione di file; * * non e possibile aprire il file all'interno dell'oggetto zip; * * non e possibile creare il file estratto; * * si e rilevato un errore nella copia dei dati (1); * * non e stato possibile chiudere il file all'interno dell'oggetto zip (1); * * (1): prima di uscire dalla funzione cancella il file estratto. */ bool JlCompress::extractFile(QuaZip* zip, QString fileName, QString fileDest) { // zip: oggetto dove aggiungere il file // filename: nome del file reale // fileincompress: nome del file all'interno del file compresso // Controllo l'apertura dello zip if (!zip) return false; if (zip->getMode()!=QuaZip::mdUnzip) return false; // Apro il file compresso if (!fileName.isEmpty()) zip->setCurrentFile(fileName); QuaZipFile inFile(zip); if(!inFile.open(QIODevice::ReadOnly) || inFile.getZipError()!=UNZ_OK) return false; // Controllo esistenza cartella file risultato QDir curDir; if (!curDir.mkpath(QFileInfo(fileDest).absolutePath())) { return false; } if (QFileInfo(fileDest).isDir()) return true; // Apro il file risultato QFile outFile; outFile.setFileName(fileDest); if(!outFile.open(QIODevice::WriteOnly)) return false; // Copio i dati if (!copyData(inFile, outFile) || inFile.getZipError()!=UNZ_OK) { outFile.close(); removeFile(QStringList(fileDest)); return false; } outFile.close(); // Chiudo i file inFile.close(); if (inFile.getZipError()!=UNZ_OK) { removeFile(QStringList(fileDest)); return false; } return true; } /** * Rimuove i file il cui nome e specificato all'interno di listFile. * Restituisce true se tutti i file sono stati cancellati correttamente, attenzione * perche puo restituire false anche se alcuni file non esistevano e si e tentato * di cancellarli. */ bool JlCompress::removeFile(QStringList listFile) { bool ret = true; // Per ogni file for (int i=0; i added; // Aggiungo i file e le sotto cartelle if (!compressSubDir(&zip,dir,dir,recursive, added)) { QFile::remove(fileCompressed); return false; } // Chiudo il file zip zip.close(); if(zip.getZipError()!=0) { QFile::remove(fileCompressed); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /**OK * Estrae il file fileName, contenuto nel file fileCompressed, con il nome fileDest. * Se fileDest = "" allora il file viene estratto con lo stesso nome con cui e * stato compresso. * Se la funzione fallisce cancella il file che si e tentato di estrarre. * Restituisce il nome assoluto del file estratto. * * La funzione fallisce se: * * non si riesce ad aprire l'oggetto zip; * * l'estrazione del file fallisce; * * non si riesce a chiudere l'oggetto zip; */ QString JlCompress::extractFile(QString fileCompressed, QString fileName, QString fileDest) { // Apro lo zip QuaZip zip(fileCompressed); if(!zip.open(QuaZip::mdUnzip)) { return QString(); } // Estraggo il file if (fileDest.isEmpty()) fileDest = fileName; if (!extractFile(&zip,fileName,fileDest)) { return QString(); } // Chiudo il file zip zip.close(); if(zip.getZipError()!=0) { removeFile(QStringList(fileDest)); return QString(); } return QFileInfo(fileDest).absoluteFilePath(); } /**OK * Estrae i file specificati in files, contenuti nel file fileCompressed, nella * cartella dir. La struttura a cartelle del file compresso viene rispettata. * Se dir = "" allora il file viene estratto nella cartella corrente. * Se la funzione fallisce cancella i file che si e tentato di estrarre. * Restituisce i nomi assoluti dei file estratti. * * La funzione fallisce se: * * non si riesce ad aprire l'oggetto zip; * * l'estrazione di un file fallisce; * * non si riesce a chiudere l'oggetto zip; */ QStringList JlCompress::extractFiles(QString fileCompressed, QStringList files, QString dir) { // Creo lo zip QuaZip zip(fileCompressed); if(!zip.open(QuaZip::mdUnzip)) { return QStringList(); } // Estraggo i file QStringList extracted; for (int i=0; iopen(QuaZip::mdUnzip)) { delete zip; return QStringList(); } // Estraggo i nomi dei file QStringList lst; QuaZipFileInfo info; for(bool more=zip->goToFirstFile(); more; more=zip->goToNextFile()) { if(!zip->getCurrentFileInfo(&info)) { delete zip; return QStringList(); } lst << info.name; //info.name.toLocal8Bit().constData() } // Chiudo il file zip zip->close(); if(zip->getZipError()!=0) { delete zip; return QStringList(); } delete zip; return lst; }