miniLZO是一种轻量级的压缩和解压缩库,它是基于LZO压缩和解压缩算法实现的。LZO虽然功能强大,但是编译后的库文件较大,而minilzo编译后的库则小于5kb,因此miniLZO为那些仅需要简单压缩和解压缩功能的程序而设计。
实现miniLZO的源码很简单,包含如下文件:
edsionte@virtualPC ~/minilzo-2.06 $ tree . ├── COPYING ├── lzoconf.h ├── lzodefs.h ├── Makefile ├── minilzo.c ├── minilzo.h ├── README.LZO └── testmini.c
在程序中加入miniLZO压缩和解压缩功能的方法很简单,只需将源文件minilzo.c和头文件lzoconf.h,lzodefs.h和minilzo.h拷贝到源文件目录下,在源代码中加入头文件minilzo.h,并且在编译时加入miniloz.c。
如何在源程序中具体使用miniLZO的压缩和解压缩功能?下面将给出一个简单的实例程序来说明使用方法。该程序所演示的功能是:首先利用minilzo提供的压缩API将指定文件的前1024字节进行压缩,并将压缩后的内容保存在cfile文件中;然后将该压缩文件的内容再进行解压缩,并存入另一个文件dcfile中。
正如上面所描述的那样,要使用miniLZO,必须加入头文件minilzo.h。
#include "minilzo.h" #define MAX_LEN 1024 #define HEAP_ALLOC(var,size) \ lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] //the wkmem is used for compressed static HEAP_ALLOC(wkmem, LZO1X_1_MEM_COMPRESS);
除此之外,定义一个宏HEAP_ALLOC,它为压缩提供一个内存空间。要使用压缩或解压缩功能,必须先通过lzo_init()对miniLZO对应的库进行初始化。
int main() { int fd; char *srcbuffer = NULL, *destbuffer = NULL; lzo_uint inlen = MAX_LEN; lzo_uint outlen = 0; lzo_uint newlen = 0; //init the lzo lib if (lzo_init() != LZO_E_OK) { printf("lzo_init error.\n"); return -1; }
打开要压缩的文件,将数据读入内存的缓冲区中。
if ((fd = open("./minilzo.c", O_RDONLY)) < 0) { printerror(__LINE__, errno, "open"); } //alloc the src buffer and dest buffer if ((srcbuffer = malloc(MAX_LEN)) < 0) { printerror(__LINE__, errno, "malloc"); } if ((destbuffer = malloc(MAX_LEN)) < 0) { printerror(__LINE__, errno, "malloc"); } memset(srcbuffer, 0, MAX_LEN); memset(destbuffer, 0, MAX_LEN); if (read(fd, srcbuffer, MAX_LEN) < 0) { printerror(__LINE__, errno, "read"); }
利用压缩接口lzo1x_1_compress()将srcbuffer中长度为inlen的数据进行压缩,并将压缩后的数据保存在destbuffer中,其压缩数据的长度返回到值结果参数outlen中。其中wkmem为压缩数据时所需要的内存空间。
int ret; if ((ret = lzo1x_1_compress(srcbuffer, inlen, destbuffer, &outlen, wkmem)) != LZO_E_OK) { printf("compress error:%d.\n", ret); return -1; } else { printf("compress %lu bytes into %lu bytes.\n", (unsigned long)inlen, (unsigned long)outlen); } if (outlen >= inlen) { printf("This block contains incompressible data.\n"); return 0; }
下面将压缩后的数据保存到新文件cfile中。
int cfd; if ((cfd = open("./cfile", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { printerror(__LINE__, errno, "open"); } if (write(cfd, destbuffer, outlen) < 0) { printerror(__LINE__, errno, "write"); }
接着进行解压缩过程,利用lzo1x_decompress()则可以完成。各个参数的意义与压缩时相同,只不过要调整源数据和目的数据之间的方向。
memset(srcbuffer, 0, MAX_LEN); if ((ret = lzo1x_decompress(destbuffer, outlen, srcbuffer, &newlen, NULL)) != LZO_E_OK) { printf("decompress error:%d.\n", ret); return -1; } else if ( inlen == newlen) { printf("decompress %lu bytes into %lu bytes.\n", (unsigned long)outlen, (unsigned long)newlen); }
最后将解压缩的数据写入新文件对此dcfile中。
int dcfd; if ((dcfd = open("./dcfile", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { printerror(__LINE__, errno, "open"); } if (write(dcfd, srcbuffer, newlen) < 0) { printerror(__LINE__, errno, "write"); } close(fd); close(cfd); close(dcfd); printf("compress success!\n"); return 0; }
上述为源代码,如果使用make编译文件,则Makefile为:
edsionte@virtualPC ~/edsionte-code/lzo $ cat Makefile target:=testlzo source:=testlzo.c minilzo.c default: gcc -o $(target) $(source) clean: rm $(target)
执行后,可查看两个文件的大小差异:
edsionte@virtualPC ~/edsionte-code/lzo $ ls -l cfile dcfile -rw------- 1 edsionte edsionte 265 6月 19 10:23 cfile -rw------- 1 edsionte edsionte 1024 6月 19 10:23 dcfile
可以看出minilzo的压缩率大约为1:4。