Loading

bzip2库libbzip2使用(二):高级接口

说明

bzip2提供了底层接口,高级接口以及两个实用函数(Utility functions),高级接口用来操作文件。

从网上下载bzip2库,我下载的是V1.0.8版本的。
然后在C工程中添加一个筛选器(文件夹)名叫bzip,然后把下载的库中的如下9个文件,添加到其中(代码文件组织方式仅供参考):

image

代码

主函数代码如下:

#include <stdio.h>
#include "bzlib/bzlib.h"
int main()
{
    FILE* f;        //用来接收打开文件的句柄
    BZFILE* b;      //用来接收库函数:BZ2_bzReadOpen打开的文件
    char buf[1024]; //用来接收库函数:BZ2_bzRead读取出的字节
    int bzerror;    //用来接收库抛出的成功/错误代码
    int nOpen;      //用来接收BZ2_bzRead读取出的字节的长度
    char fileName[] = "bz2/gbk.txt.bz2";
    int stop = 1;   //停止读取文件流的标志

    f = fopen(fileName, "rb"); // 设置2进制只读
    if (f == NULL) {
        printf("文件不存在");
        return;
    }
    b = BZ2_bzReadOpen(
        &bzerror, // 错误码
        f,        // 文件指针
        0,        // 范围0-4,数字越大,monitoring/debugging输出越冗长
        1,        // 设置为不为0的数,则使用另一种压缩算法,这种算法少一半的内存消耗,代价是速度变慢
        NULL,     // 不使用
        0         // 不使用
    );
    while (stop) {
        if (bzerror == BZ_OK) // 成功打开
        {
            int num = sizeof(buf);
            nOpen = BZ2_bzRead(&bzerror, b, buf, num);
            if (bzerror == BZ_OK) { //读取成功
                for (int i = 0; i < sizeof(buf); i++) {     //以字符形式循环打印出读到的字节
                    printf("%c", buf[i]);
                }
            }
            else if (bzerror == BZ_STREAM_END) {    //读到了文件流(库手册中称为逻辑流)的末尾
                for (int i = 0; i < nOpen; i++) {   //以字符形式循环打印出读到的字节
                    printf("%c", buf[i]);
                }
                stop = 0;   //退出循环读取
            }
            else if (bzerror == BZ_MEM_ERROR)
            {
                printf("没有足够的内存可用");
            }
            else {  //其他情况
                printf("读取遇到错误,错误码:%d", bzerror);
            }
        }
        else // 打开失败立即关闭文件
        {
            BZ2_bzReadClose(&bzerror, b);
        }
    }
    //关闭文件
    BZ2_bzReadClose(&bzerror, b);
    fclose(f);
}

其中最重要的点是: BZFILE* b这个结构体接收BZ2_bzReadOpen返回的结构体,其中包含了许多的信息。我们使用BZ2_bzRead读取的话,无需关注读取的文件的大小,每次读取到了哪个字节,因为这些信息都在被BZFILE* b内部记录了,我们只需要循环调用BZ2_bzRead,把b传进去即可。它会自动往下读,我们在每次读取完成后,把缓冲区的字节拿出来即可。注意检查bzerror == BZ_STREAM_END,如果相等,说明读到了文件末尾。这时需要关闭循环读取。并且关闭文件。

测试

首先在工程所在的文件夹下创建一个文件夹bz2,然后使用vscode在其中创建一个文件bgk.txt,在其中输入一些文字:

中文测试:你好世界!
数字测试:123456
English:hello world!

使用vscode的原因是它能方便地改变文件的编码,所以使用其他的文本编辑器也可以。

更改这个文件为gbk编码,因为控制台输出是gbk格式。
然后使用压缩软件把gbk.txt打一个.bz2的压缩包。打包完成的文件名应该是gbk.txt.bz2,这个压缩包在bz2文件夹。上述代码中,文件名fileName[]赋值为 "bz2/gbk.txt.bz2",这样代码就能找到这个文件了。

然后执行代码,可以看到控制台输出了gbk.txt的内容,说明解压成功:
image

本文使用了libbzip2库(即bzlib.h)中高级接口的三个函数:BZ2_bzReadOpen、BZ2_bzRead、BZ2_bzReadClose。其他低级接口、高级接口、通用接口的函数暂没有使用。可详阅官方手册:https://sourceware.org/bzip2/manual/manual.html
搭配DeepL翻译使用更佳。

posted @ 2023-01-06 15:13  sq800  阅读(1037)  评论(0编辑  收藏  举报