A. 編譯quazip.so.*
教學網址1:====================================
http://youtu.be/mxlcKmvMK9Q?list=LLcsQ3NYhHn8OW_a8V1WHebg
P.S.完整教學影片, 真的超級仔細, 其實下面自己寫下來的步驟看影片就有了,
影片也包含Windows的部分, 但我僅需Linux
1. 從 http://www.zlib.net/ 下載 zlib
解壓縮後進入zlib目錄, 指令#./configure並且#make (產生.a檔, 與.so.*檔)
3. 從 http://sourceforge.net/projects/quazip/ 下載quazip源碼包,
解壓縮後出現 quazip-0.7/ 目錄
2. 把zlib目錄下的zconf.h以及zlib.h放入quazip-0.7/quazip/目錄中
3. 將quazip-0.7/quazip/的pro檔作編輯, 加入以上兩個.h檔
4. 同樣將quazip-0.7/quazip/的pro檔作編輯,
加入在步驟1. 中, zlib產生的.a檔, 與.so.*檔
LIBDIR += "/放置zlib產生的.a檔, 與.so.*檔的目錄"
INCLUDEPATH += $${LIBDIR}
LIB += -L$${LIBDIR} -lz
5. 在quazip-0.7/quazip/下, 指令 #qmake; make
教學網址2: ===============================
http://blog.csdn.net/houqd2012/article/details/22957675
以下內容複製於此網址
QT的提供了qCompress/qUncompress方法來提供文件的壓縮與解壓,但是它存在的一個問題是:它只是單純地將一個文件壓縮為某種格式的壓縮文件,但是壓縮後的文件無法通過其它解壓工具打開,例如:7zip,或winRar,只能通過qUncompress將它解壓讀取出來,也就是說qCompress生成的壓縮文件不包含普通壓縮文件的一些頭信息,導致無法解壓。
QuaZip是使用QT、C++對zlib進行簡單封裝的用於壓縮zip以及解壓縮zip的開源庫。適用於多種平台。利用它可以很方便的將單個或多個文件打包為zip文件,且打包後的zip文件可以通過其它工具打開,滿足我們的需求。
QuaZip編譯:
注意:QuaZip是基於ZLIB庫的,因此編譯之前必須編譯完ZLIB或者導入ZLIB的頭文件。這裡編譯的過程中採用後者,因為很簡單,編譯完成後我們使用它的dll、lib以及.h頭文件。
QuaZip源碼包下載地址:http://sourceforge.net/projects/quazip/
利用VS2010打開QT項目,然後編譯,由於沒有zlib.h文件,它會報出如下錯誤:fatal error C1083: Cannot open include file: 'zlib.h': No such file or directory
解決方法,將zlib.h放入該項目中,我的QT版本是:4.8.3,在它src的第三方庫中已經包含了zlib庫,zlib庫在QT中的目錄為:D:\QT \4.8.4\src\3rdparty\zlib
從該目錄下拷貝zlib.h到QuaZip項目中,重新編譯又會報出如下的錯誤:fatal error C1083: Cannot open include file: 'zconf.h': No such file or directory
解決方法一樣,在D:\QT\4.8.4\src\3rdparty\zlib中將zconf.h文件拷貝到QuaZip目錄下,重新編譯,成功。
在項目中:我們需要用的就是它編譯產生的dll、lib以及QuaZip中用到的.h頭文件。
================= 複製結束 ===================
B. Sample code測試
以下sample code測試了
1. 加入密碼
2. 在zip壓縮檔中建立目錄結構
3. 由於我本身功能需要實現一邊寫zip檔, 一邊顯示進度條(QProgressBar), 故我寫檔時, 並非將來源檔一次readall 讀取所有data寫入zip中,
而是一次寫1M(每寫1M就顯示一次進度條), 這個部分會讓sample code看起來比較亂一點, 如果想看簡單的範例可以直接點進教學網址1:
http://blog.csdn.net/houqd2012/article/details/22957675
void MainWindow::testZIP() { QStringList srcFilesList ; qint64 nCopySize_Byte; qint64 nCopySize_MB; QString str_3, str; qint64 nCopySize_lessThan1MB; int showValue_progressBar = 0; int totalFilesSize = 12345;//需自行計算, 此值只用來測試 QString filePathInZIP; FilesCopyProgressBar->setMaximum(totalFilesSize); srcFilesList.append(QString("/^029.avi")); srcFilesList.append(QString("/^001.jpg")); srcFilesList.append(QString("/^002.jpg")); srcFilesList.append(QString("/^004.jpg")); srcFilesList.append(QString("/^006.jpg")); srcFilesList.append(QString("/^007.jpg")); srcFilesList.append(QString("/^008.jpg")); srcFilesList.append(QString("/^010.jpg")); QString zipLocation = "/media/sda1/20141028-TEST.zip"; QuaZip zip(zipLocation); zip.setFileNameCodec("IBM866"); if(!zip.open(QuaZip::mdCreate)){ qDebug() << "error .... 1"; } QuaZipFile outFile(&zip); for(int i = 0 ; i < srcFilesList.size() ; i++) { QFileInfo file(srcFilesList.at(i)); if(file.exists()) { QFile inFile ; inFile.setFileName(file.filePath()); if(!inFile.exists()) { qDebug()<<"error .... 1.5: inFile "<<inFile.fileName()<<"is not exist!!"; } if(!inFile.open(QIODevice::ReadOnly)){ qDebug() << "error ....2"; //qDebug() << inFile.errorString().toLocal8Bit().constData(); } // 建立zip中的目錄結構 if(i < 2) // /^029.avi與 /^001.jpg 放入第一層目錄中 filePathInZIP = QString("TEST_FOLDER1/")+ file.fileName(); else if(i < 4) // /^002.jpg與 /^004.jpg 放入第二層目錄中 filePathInZIP = QString("TEST_FOLDER1/TEST_FOLDER2/")+ file.fileName(); else if(i < 6) filePathInZIP = QString("TEST_FOLDER1/TEST_FOLDER2/TEST_FOLDER3/")+ file.fileName(); else filePathInZIP = QString("TEST_FOLDER1/TEST_FOLDER2/")+ file.fileName(); if(!outFile.open(QIODevice::WriteOnly , QuaZipNewInfo(filePathInZIP , inFile.fileName()), "12345678")){ qDebug() << "error ...3"; } //outFile.write(inFile.readAll()); //---------------------- nCopySize_Byte = inFile.size(); nCopySize_MB = nCopySize_Byte / ((qint64) 1048576); nCopySize_lessThan1MB = nCopySize_Byte % ((qint64) 1048576); showValue_progressBar = 0; qDebug()<<"QFile inFile: file name="<<inFile.fileName(); for (qint64 j = 0; j < nCopySize_MB+((qint64) 1); j++) { //qDebug() << "i = " << i; str_3.clear(); str.clear(); if(!inFile.flush()) qDebug("%s(%d): Flush file - %s failed", __FUNCTION__, __LINE__, inFile.fileName().toAscii().data()); inFile.seek(j*((qint64) 1048576)); // move to next byte to read outFile.seek(j*((qint64) 1048576)); // move to next byte to write if(j < nCopySize_MB) outFile.write(inFile.read((qint64) 1048576), (qint64) 1048576); // write a MB byte else outFile.write(inFile.read(nCopySize_lessThan1MB), nCopySize_lessThan1MB); showValue_progressBar = (int)((j*1048576 + nCopySize_lessThan1MB)/1024); str = QString("Copy %1\n%2 / %3KB").arg(srcFilesList.at(i)).arg(showValue_progressBar).arg(totalFilesSize); /* .......................... 將str顯示於進度條, 並且設定showValue_progressBar為目前進度條完成的值 ........................... */ } //---------------------- if(outFile.getZipError() != UNZ_OK){ qDebug() << "error ...4"; } outFile.close(); if(outFile.getZipError() != UNZ_OK){ qDebug() << "error ....5"; } inFile.close(); } } zip.close(); if(zip.getZipError()){ qDebug() << "error ...6"; } system("sync;sync"); }
最後在/media/sda1/ 下產出 20141028-TEST.zip, 並且八個檔案都在其中,
且放置於我寫死的目錄結構之下
C. 較進階的設定 - 密碼與壓縮層級
測試以上sample code後發現, 可正常運行但壓縮速度比直接複製還要慢很多,
但我需要減少壓縮時間
故需要把壓縮率調低,
所以我觀察了QuaZipFile.h檔中的open函式宣告的註解,
看開檔時帶入的參數中是否有壓縮率
(我的需求僅需要加密碼, 至於壓縮並不需要努力壓XD)
open函式的參數設定(此函式是多載的, 如果不需要這麼複雜可以用其他的):
bool QuaZipFile::open(OpenMode mode,
const QuaZipNewInfo &info,
const char * password=NULL,
quint32 crc=0,
int method=Z_DEFLATED,
int level=Z_DEFAULT_COMPRESSION,
bool raw=false,
int windowBits=-MAX_WBITS,
int memLevel=DEF_MEM_LEVEL,
int strategy=Z_DEFAULT_STRATEGY);
/// Opens a file for writing. 打開一個檔案以寫入壓縮檔中
/** \a info argument specifies information about file. It should at
* least specify a correct file name. Also, it is a good idea to
* specify correct timestamp (by default, current time will be
* used). See QuaZipNewInfo.
* The \a password argument specifies the password for crypting. Pass NULL
* if you don't need any crypting. The \a crc argument was supposed
* to be used for crypting too, but then it turned out that it's
* false information, so you need to set it to 0 unless you want to
* use the raw mode (see below).
其中 const char * password=NULL
是用來帶入加密的密碼, 如果不須加密可帶入NULL.
而 quint32 crc=0
是用來被使用於支持加密, 預設為false, 如果需要使用raw mode(下面會有說明)則要設為true.
* Arguments \a method and \a level specify compression method and
* level. The only method supported is Z_DEFLATED, but you may also
* specify 0 for no compression. If all of the files in the archive
* use both method 0 and either level 0 is explicitly specified or
* data descriptor writing is disabled with
* QuaZip::setDataDescriptorWritingEnabled(), then the
* resulting archive is supposed to be compatible with the 1.0 ZIP
* format version, should you need that. Except for this, \a level
* has no other effects with method 0.
int method=Z_DEFLATED 以及 int level=Z_DEFAULT_COMPRESSION
用來標明壓縮方法以及層級.
method 僅支持 Z_DEFLATED , 但若為不壓縮( no compression ) 您可標註0.
如果在壓縮檔中的所有檔案都使用method=0 , 則無論是帶入level=0 或者是使用QuaZip::setDataDescriptorWritingEnabled(false) 函式代入false,
壓縮檔結果會被支持兼容於 1.0 ZIP格式版本 (如果你需要的話)
除此之外, 在method為0下, 層級(level)並沒有其他影響.
* If \a raw is \c true, no compression is performed. In this case,
* \a crc and uncompressedSize field of the \a info are required.
*
* Arguments \a windowBits, \a memLevel, \a strategy provide zlib
* algorithms tuning. See deflateInit2() in zlib.
**/
如果raw mode被設為true, 則不實行壓縮. 在此case下, 需要crc以及未壓縮尺寸區域( uncompressedSize field )之資訊