close
 
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 )之資訊

 

 

 
arrow
arrow
    文章標籤
    QT QuaZip Linux
    全站熱搜
    創作者介紹
    創作者 lynn770707 的頭像
    lynn770707

    雜記

    lynn770707 發表在 痞客邦 留言(0) 人氣()