寫作目的:之前在網上看到很多人在尋找可以解壓縮多個文件的程序,其中有嘗試zlib的,使用zlib的源碼可以生成后綴為點gz的壓縮文件,但是一次只能壓縮一個文件,無法壓縮多個文件。其實,zlib的源碼包里有一個第三方的contrib已經實現解壓縮多個文件,這就是minizip。下面就來看看是怎么操作的。
下載zlib源碼
去zlib網站http://www.zlib.net/,下載源碼並解壓
這里選擇tar.gz格式的源碼包下載(其它格式都可以)
編譯zlib
進入到zlib-1.2.11目錄下,發現有個Makefile文件,打開如下,
這是個提示,讓我們先運行./configure。按照提示我們在終端輸入./configure並回車,運行完畢后再打開看Makefile,發現里面就有內容了,
此時在終端輸入make,這樣zlib源碼就開始編譯了。
編譯完畢后如果輸入make install,就可以把編譯好的zlib庫放在系統路徑里,以后寫代碼就可以直接調用zlib提供的庫函數了。
以上這些操作信息是寫在源碼目錄下的readme文件里的,這里截取一段,
還有講example的,告訴我們example源碼在哪。
源碼目錄下還有個INDEX文件,里面敘述了構成zlib的所有public header files和private source files,有了這些信息,就可以很方便的把需要的源碼集成到自己的工程中去。
可以看出作者的文檔寫的非常好。
minizip
下面就來解決之前說的問題:解壓縮多個文件(基於minizip)。
minizip源碼目錄在zlib-1.2.11/contrib目錄下,進入這個目錄,先看下該目錄下的README.contrib文件,這個文件描述了基於zlib寫的的第三方contributions,找到minizip
有個Makefile,打開如下,
內容比較簡單,就是編譯出2個elf文件:miniunz和minizip。通過名字就可以知道一個是用來解壓,另一個用來壓縮。
其中,
- 生成miniunz需要用到miniunz.c,unzip.c,ioapi.c和之前編譯zlib時生成的靜態庫libz.a
- 生成minizip需要用到minizip.c,zip.c,ioapi.c和之前編譯zlib時生成的靜態庫libz.a
輸入make執行Makefile,會有幾個warning,
定位到miniunz.c的100行,
這種條件編譯寫法是比較老的,現在編譯器已經不提倡這種寫法了,所以改為如下,
再編譯就沒這個warning了,按照這種方法也可以消除minizip.c中97行的warning。最后還剩個mkdir未聲明,一般這是因為沒有對應的頭文件導致的,在終端輸入man 2 mkdir並回車,
可以看出mkdir對應的是2個頭文件,把這2個頭文件添加到miniunz.c里,再次編譯,就沒有任何warning了。
編譯完成后,就可以在minizip目錄下看到2個elf文件:miniunz和minizip。這里先測試一下minizip,在終端輸入./minizip -h並回車,得到以下幫助信息,
我們在minizip目錄下新建一個目錄test,然后把minizip拷貝進去,然后在test目錄下建2個文件a.txt和b.txt,隨意寫點內容在里面。
然后按照之前的幫助信息,輸入./minizip -o -9 target.zip a.txt b.txt 並回車,可以發現生成了target.zip文件,打開它發現實現了多個文件的壓縮,
再來測試下miniunz,先把a.txt和b.txt刪除,再把miniunz拷貝進來。先看下miniunz的幫助信息,輸入./miniunz -h並回車,結果居然有error,說明這個miniunz.c里的main函數寫的不夠好,沒有對-h的支持,畢竟是第三方contributions
不過沒關系,一般來說-h不行,那么就直接./miniunz回車,這次幫助信息出來了,
我們輸入./miniunz -x target.zip,提示解壓成功,我們看下目錄,確實OK了。
加密解壓縮
解壓縮多個文件已經測試OK,下面就來測試以下加密解壓縮多個文件,畢竟minizip和miniunz的幫助信息里顯示是支持加密的。
先測試minizip的加密功能,終端下輸入./minizip -o -9 -p 123 target_crypt.zip 1.txt 2.txt並回車,可以看到生成了target_crypt.zip文件,雙擊打開它,提示需要輸入密碼,
我們輸入123,發現可以正確打開,說明加密功能沒問題。
下面測試一下miniunz的解密功能(先把a.txt和b.txt刪除),終端輸入./miniunz -x -p 123 targer_crypt.zip並回車,發現竟然無法解密,
根據提示,是unzOpenCurrentFilePassword()函數返回了-102,我們去找一下unzOpenCurrentFilePassword()的定義,回到minizip目錄下使用grep去查找,
發現該函數定義在unzip.c里,打開unzip.c找到這個函數,
函數開始處就有個可能返回的值UNZ_PARAMERROR,再用grep查下這個宏定義,
發現這個值就是-102,看來函數運行到這個return語句了。再看下代碼,可以推斷出NOUNCRYPT被定義了,而這個宏從字面感覺是沒有密碼的意思,難道miniunz的工程屏蔽了解密功能?我們再用grep查下NOUNCRYPT,看下在哪里設置的,
可以看出是在unzip.c里定義的宏,進去查看下,
果然是定義了NOUNCRYPT,把解密功能屏蔽了。既然找到了問題的根源,那么解密失敗的問題就迎刃而解了:把這三行語句屏蔽掉,然后重新編譯,重新生成miniunz,並拷貝到test目錄下。再次輸入./miniunz -x -p 123 target_crypt.zip並回車,就可以了。
看來這個miniunz還是有點小bug的,不過仔細研究下也很容易解決。
總結
minizip可以達到解壓縮多個文件的要求,而且其源碼也比較少,結構也簡單清晰,可以很方便地集成到自己的工程中來,或者自己修改,這就需要自己去研究下源碼了。
如果想偷懶的話,可以只看minizip.c和miniunz.c里的main函數,把它改成一個接口函數,來達到自己的需求。
如果有寫的不對的地方,希望能留言指正,謝謝閱讀。