不少網友讀完zlib庫compress和uncompress函數的使用方法這篇文章之後,仍然無法獨立完成簡單的檔案壓縮和解壓縮功能,為此作者在這裡追加這樣的示範代碼。問題的根源在於這些網友對於字串和位元組流的概念非常的模糊,對文字檔和二進位檔案的區別常常模稜兩可,其實位元組流可以表示所有的資料,二進位檔案才是任何檔案的本質。位元組流是一個位元組接一個位元組,並沒有結束符號,所以需要給它一個長度資訊。二進位檔案是一個位元組接一個位元組,並沒有分行符號之類的。
檔案壓縮的時候,可以通過源檔案的長度自動計算緩衝區的長度,壓縮後寫入目標檔案之前,需先保留源檔案和目標資料的長度作為解壓縮的依據,參考如下代碼:
#include <stdlib.h>#include <stdio.h>#include <zlib.h>int main(int argc, char* argv[]){ FILE* file; uLong flen; unsigned char* fbuf = NULL; uLong clen; unsigned char* cbuf = NULL; /* 通過命令列參數將srcfile檔案的資料壓縮後存放到dstfile檔案中 */ if(argc < 3) { printf("Usage: zcdemo srcfile dstfile\n"); return -1; } if((file = fopen(argv[1], "rb")) == NULL) { printf("Can\'t open %s!\n", argv[1]); return -1; } /* 裝載源檔案資料到緩衝區 */ fseek(file, 0L, SEEK_END); /* 跳到檔案末尾 */ flen = ftell(file); /* 擷取檔案長度 */ fseek(file, 0L, SEEK_SET); if((fbuf = (unsigned char*)malloc(sizeof(unsigned char) * flen)) == NULL) { printf("No enough memory!\n"); fclose(file); return -1; } fread(fbuf, sizeof(unsigned char), flen, file); /* 壓縮資料 */ clen = compressBound(flen); if((cbuf = (unsigned char*)malloc(sizeof(unsigned char) * clen)) == NULL) { printf("No enough memory!\n"); fclose(file); return -1; } if(compress(cbuf, &clen, fbuf, flen) != Z_OK) { printf("Compress %s failed!\n", argv[1]); return -1; } fclose(file); if((file = fopen(argv[2], "wb")) == NULL) { printf("Can\'t create %s!\n", argv[2]); return -1; } /* 儲存壓縮後的資料到目標檔案 */ fwrite(&flen, sizeof(uLong), 1, file); /* 寫入源檔案長度 */ fwrite(&clen, sizeof(uLong), 1, file); /* 寫入目標資料長度 */ fwrite(cbuf, sizeof(unsigned char), clen, file); fclose(file); free(fbuf); free(cbuf); return 0;}
檔案解壓縮的時候,可以通過保留資訊得到緩衝區和資料流的大小,這樣解壓縮後直接儲存即可,參考如下代碼:
#include <stdlib.h>#include <stdio.h>#include <zlib.h>int main(int argc, char* argv[]){FILE* file;uLong flen;unsigned char* fbuf = NULL;uLong ulen;unsigned char* ubuf = NULL;/* 通過命令列參數將srcfile檔案的資料解壓縮後存放到dstfile檔案中 */if(argc < 3){printf("Usage: zudemo srcfile dstfile\n");return -1;}if((file = fopen(argv[1], "rb")) == NULL){printf("Can\'t open %s!\n", argv[1]);return -1;}/* 裝載源檔案資料到緩衝區 */fread(&ulen, sizeof(uLong), 1, file);/* 擷取緩衝區大小 */fread(&flen, sizeof(uLong), 1, file);/* 擷取資料流大小 */if((fbuf = (unsigned char*)malloc(sizeof(unsigned char) * flen)) == NULL){printf("No enough memory!\n");fclose(file);return -1;}fread(fbuf, sizeof(unsigned char), flen, file);/* 解壓縮資料 */if((ubuf = (unsigned char*)malloc(sizeof(unsigned char) * ulen)) == NULL){printf("No enough memory!\n");fclose(file);return -1;}if(uncompress(ubuf, &ulen, fbuf, flen) != Z_OK){printf("Uncompress %s failed!\n", argv[1]);return -1;}fclose(file);if((file = fopen(argv[2], "wb")) == NULL){printf("Can\'t create %s!\n", argv[2]);return -1;}/* 儲存解壓縮後的資料到目標檔案 */fwrite(ubuf, sizeof(unsigned char), ulen, file);fclose(file);free(fbuf);free(ubuf);return 0;}