Node.js——zlib压缩模块

zlib压缩模块

1、创建压缩及解压缩的对象

在zlib模块中,提供表中的几个方法用于创建各种对数据进行压缩及解压缩处理的对象。

方法 说明
zlib.createGzip [options]) 该方法创建并返回一个Gzip对象,该对象使用Gzip算法对数据进行压缩处理
zlib.createDeflate ([options]) 该方法创建并返回一个Deflate对象,该对象使用Deflate算法对数据进行压缩处理
zlib.createDeflateRaw [options]) 该方法创建并返回一个DeflateRaw对象,该对象使用Deflate算法对数据进行压缩处理。在压缩数据中不添加zlib头
zlib.createGunzip [options]) 该方法创建并返回一个Gunzip对象,该对象对使用Gzip算法进行压缩的数据进行解压缩处理
zlib.createInflate [options]) 该方法创建并返回一个Inflate对象,该对象对使用Deflate对象进行压缩的数据进行解压缩处理
zlib.createInflateRaw ([options]) 该方法创建并返回一个InflateRaw对象,该对象对使用DeflateRaw对象进行压缩的数据进行解压缩处理
zlib.createUnzip [options] 该方法创建并返回一个Unzip对象,该对象既可对使用Gzip算法进行压缩的数据进行解压缩处理,也可对使用Deflate算法进行压缩的数据进行解压缩处理。根据压缩数据中的zb头来判断该数据是使用哪一种算法进行压缩的数据

上表描述的各个方法均采用一个可选的options参数,该参数值为一个对象,用于指定压缩或解压缩数据时所使用的选项。该对象可以使用的属性及属性值如下所示(有些属性只用于压缩数据时)​。

  • flush:用于设定或读取压缩方法及状态,可指定属性值如下。
  • zlib.Z_NO_FLUSH:flush属性的默认属性值,该模式运行在数据被输出之前,预先决定每次压缩多少数据,以实现最大化压缩。
  • zlib.Z_SYNC_FLUSH:该属性值用于指定将压缩数据分为若干个压缩块,每次将一个压缩块中的数据写入输出缓存区,然后在数据块后面写入一个10位长度的空白数据块。当使用某些压缩算法时,这种模式可能会降低数据的压缩程度,因此,只应该使用在必须使用的场合。
  • zlib.Z_PARTIAL_FLUSH:该属性值用于指定在压缩数据时每次都将输出缓存区所能容纳的数据写入输出缓存区,不限制输出数据的字节数。
  • zlib.Z_FULL_FLUSH:与Z_SYNC_FLUSH相同,预先将压缩数据分为若干个压缩块,然后在数据块后面写入一个10位长度的空白数据块。但是在数据块写完后复位压缩状态,因此,当压缩的数据流被管道输出时,解压缩该数据的另一端可以在前次数据被破坏时要求重新压缩。
  • zlib.Z_FINISH:当属性值为zlib.Z_FINISH时,输出缓存区中的剩余数据将被全部输出。
  • chunkSize:用于设定将数据分块时每个块的大小,单位为字节,默认属性值为16*1024。
  • windowBits:该属性值为以2为底数所求出的压缩窗口的对数,用于设定压缩窗口的大小,属性值在8~15之间,默认为15。属性值越大,压缩效果越好,但是内存消耗也越多。当使用deflate算法压缩数据且在压缩数据中不使用zlib头时,属性值也可以为-15~-8的数值。
  • level:该属性值为整数值,用于指定压缩级别,属性值可以为-1或0~9的数值。当属性值为0时,不执行压缩处理。当属性值为1时,压缩速度最快,压缩程度最低。当属性值为9时,压缩速度最慢,压缩程度最高。当属性值为-1时,表示使用默认压缩比,该属性值自动在压缩速度及压缩程度之间进行妥协(大多数场合中妥协结果相当于将level属性值设定为6)。
  • memLevel:该属性值用于指定在进行压缩时为压缩程序分配多少内存,属性值为1~9之间的整数。当该属性值为1时,消耗最少的内存,但是压缩程度被降低。当该属性值为9时,消耗最多的内存,但是压缩效果最好。默认属性值为8。
  • strategy:该属性值用于调整压缩算法,可指定属性值如下。
    • zlib.Z_DEFAULT_STRATEGY,该属性值为默认属性值,用于进行标准压缩。
    • zlib.Z_HUFFMAN_ONLY,该属性值用于指定在压缩数据时使用霍夫曼编码(Huffman Coding)。霍夫曼编码是一种用于无损数据压缩的熵编码(又称权编码)算法。
    • zlib.Z_FILTERED,该属性值用于在压缩数据时对数据进行过滤,以达到更好的压缩效果。
    • zlib.Z_RLE,该属性值用于指定在压缩时采用游程编码(Run-Length Encoding,RLE)。游程编码又称行程长度编码,该编码对连续的黑、白像素数(游程)以不同的码字进行编码。游程编码是一种简单的非破坏性资料压缩法,其好处是压缩和解压缩都非常快。其方法是计算连续出现的资料长度压缩之,其缺点是对于不重复的资料反而加大容量。当对PNG图像进行压缩时,游程编码可以达到最佳的压缩效果。
    • zlib.Z_FIXED,该属性值用于指定在压缩过程中禁止使用霍夫曼编码,以达到在特殊的应用程序中简化解码过程的目的。

1.1、压缩文件

由于Gzip对象、Deflate对象与DeflateRaw对象既可用于读取流数据,又可用于写入流数据,因此,我们可以直接使用这些ReadStream对象的pipe方法将文件流数据输出到Gzip对象、Deflate对象与DeflateRaw对象中,再使用这些对象的pipe方法将使用这些对象进行压缩后的流数据输出到另一个压缩文件中。

在zlib模块中,上表中描述的各方法所创建的对象均为一个既可用于读取流数据的对象,又可用于写入流数据的对象,拥有表1及表2中描述的各种事件,拥有表3及表4中描述的各种方法。

表1:读取事件

表2:写入事件

表3:读取方法

表4:写入方法

示例:方法创建一个Gzip对象,然后为应用程序根目录下的aaa.txt文件创建一个ReadStream对象,使用该对象来读取aaa.txt文件中的数据,为应用程序根目录下的aaa.txt.gz文件创建一个WriteStream对象,然后使用ReadStream对象的pipe方法读取aaa.txt文件中的数据并将它输出到Gzip对象中进行压缩,然后使用Gzip对象的pipe方法将压缩后的数据输出到WriteStream对象,即aaa.txt.gz文件中。

js 复制代码
const zlib = require('zlib');
let gzip = zlib.createGzip();
const fs = require('fs');
let inp = fs.createReadStream('aaa.txt');
let out = fs.createWriteStream('aaa.txt.gz');
inp.pipe(gzip).pipe(out);

1.2、解压文件

由于Gunzip对象、Inflate对象、InflateRaw对象与Unzip对象既可用于读取流数据,又可用于写入流数据,因此,可以直接使用这些ReadStream对象的pipe方法读取压缩文件中的数据并将其输出到Gunzip对象、Inflate对象、InflateRaw对象或Unzip对象中,再使用这些对象的pipe方法将使用这些对象进行解压缩后的流数据还原到一个文件中。

示例:首先使用createGunzip方法创建一个Gunzip对象,然后为应用程序根目录下的aaa.txt.gz文件创建一个ReadStream对象,使用该对象来读取aaa.txt.gz文件中的数据,为应用程序根目录下的bbb.txt文件创建一个WriteStream对象,然后使用ReadStream对象的pipe方法读取aaa.txt.gz文件中的数据并将它输出到Gunzip对象中进行解压缩,接着使用Gunzip对象的pipe方法将解压缩后的数据输出到WriteStream对象,即bbb.txt文件中。

js 复制代码
const zlib = require('zlib');
const gunzip = zlib.createGunzip();
const fs = require('fs');
let inp = fs.createReadStream('aaa.txt.gz');
let out = fs.createWriteStream('bbb.txt');
inp.pipe(gunzip).pipe(out);

1.3、压缩/解压网络数据流

在HTTP服务器端与HTTP客户端之间传输压缩数据时,在客户端请求头中需要使用accept-encoding字段指定服务器端压缩数据时使用的压缩算法,在服务器端响应头中应使用content-encoding字段声明服务器端响应数据的压缩算法。

下面开始创建HTTP服务器代码,在该示例代码中:

  • 先创建一个HTTP服务器,当HTTP服务器接收到客户端请求时,获取客户端请求头中的accept-encoding字段,
    • 如果字段值中包含"deflate"字符串,创建Deflate对象并使用该对象压缩应用程序根目录下的aaa.txt文件,在服务器端响应头中将content-encoding字段值指定为"deflate",然后将压缩后的数据返回给客户端;
    • 如果accept-encoding字段值中包含"gzip"字符串,创建Gzip对象并使用该对象压缩应用程序根目录下的aaa.txt文件,在服务器端响应头中将content-encoding字段值指定为"gzip",然后将压缩后的数据返回给客户端;
    • 如果accept-encoding字段值中既不包含"deflate"字符串,又不包含"gzip"字符串,直接将应用程序根目录下的aaa.txt文件中的数据返回给客户端。
js 复制代码
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
//创建HTTP服务端
http.createServer((request, response)=>{
    let raw = fs.createReadStream('aaa.txt');
    //获取header
    let acceptEncoding = request.headers['accept-encoding'];
    //判断压缩算法
    if (!acceptEncoding) {
        acceptEncoding = '';
    }
    if (acceptEncoding.match(/\bdeflate\b/)) {
        response.writeHead(200, { 'content-encoding': 'deflate' });
        raw.pipe(zlib.createDeflate()).pipe(response);
    } else if (acceptEncoding.match(/\bgzip\b/)) {
        response.writeHead(200, { 'content-encoding': 'gzip' });
        raw.pipe(zlib.createGzip()).pipe(response);
    } else {
        response.writeHead(200, {});
        raw.pipe(response);
    }
}).listen(1337);
  • 接下来创建用于向HTTP服务器请求数据的HTTP客户端,向HTTP服务器请求数据,将客户端请求头中的accept-encoding字段值设定为"gzip,deflate"。在接收到服务器端响应后,获取响应头中的content-encoding字段值
    • 如果字段值为"gzip",创建Gunzip对象并使用该对象解压缩服务器端响应数据并将其写入应用程序根目录下的raw.txt文件中;
    • 如果content-encoding字段值为"deflate",创建Inflate对象并使用该对象解压缩服务器端响应数据并将其写入应用程序根目录下的raw.txt文件中;
    • 如果content-encoding字段值既不等于"gzip",也不等于"deflate",将服务器端响应数据直接写入应用程序根目录下的raw.txt文件中。
js 复制代码
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
//构建请求
let request = http.get({ host: 'localhost',
                    path: '/',
                    port: 1337,
                    headers: { 'accept-encoding': 'gzip,deflate' } });
//监听响应
request.on('response', (response)=>{
    let output = fs.createWriteStream('raw.txt');
    switch (response.headers['content-encoding']) {
        case 'gzip':
            response.pipe(zlib.createGunzip()).pipe(output);
            break;
        case 'deflate':
            response.pipe(zlib.createInflate()).pipe(output);
            break;
        default:
            response.pipe(output);
            break;
    }
});

2、zlib模块中的各种方法

在zlib模块中,除了各种用于创建对数据进行压缩及解压缩处理的对象的方法之外,还提供了表中的各种方法。所有这些方法的第一个参数值均为一个字符串或Buffer对象,在方法内部对该字符串或Buffer对象所引用的缓存区中的数据进行压缩或解压缩。在这些方法中不使用在各种用于创建对数据进行压缩及解压缩处理的对象的方法中所使用的options参数,即在压缩或解压缩时使用各种默认选项。所有这些方法的第二个参数值均为一个回调函数,用于指定压缩或解压缩数据结束时需要执行的处理。该回调函数中的第一个参数值为压缩或解压缩数据失败时触发的错误对象,该回调函数中的第二个参数值为一个Buffer对象,该Buffer对象所引用的缓存区中存放了压缩或解压缩后的数据。

各种用于压缩或解压缩数据的方法:

方法 说明
zlib.gzip(buf,callback) 使用Gzip算法压缩buf字符串或buf缓存区中的数据
zlib.deflate(buf,callback) 使用Deflate算法压缩buf字符串或buf缓存区中的数据
zlib.deflateRaw(buf,callback) 使用Deflate算法压缩buf字符串或buf缓存区中的数据。在压缩数据中不添加zib头
zlib.gunzip(buf,callback) 使用Gunzip算法解压缩buf缓存区中的数据
zlib.inflate(bu,callback) 使用Inflate算法解压缩buf缓存区中的数据
zlib.inflateRaw(buf,callback) 使用Inflate算法解压缩buf缓存区中的数据。在压缩数据中不使用zlib头
zlib.unzip(buf,callback) 该方法既可使用Gunzip算法解压缩buf缓存区中的数据,又可使用Inflate算法解压缩buf缓存区中的数据。根据压缩数据中的zib头来判断使用哪一种算法解压缩数据

示例:使用gzip方法压缩"abcdefghijklmnopqrstuvwxyz"字符串,并且在gzip方法所使用的回调函数中指定将压缩数据输出到应用程序根目录下的compress.log文件中,然后使用unzip方法解压缩被压缩数据,并且将解压缩数据输出到控制台中。

js 复制代码
const zlib = require('zlib');
const fs = require('fs');
let out=fs.createWriteStream('aaa.txt');
let input = 'abcdefghijklmnopqrstuvwxyz';
zlib.gzip(input,(err,buffer)=>{
    if (!err) {
        zlib.unzip(buffer,(err,buffer)=>{
            if (!err) {
                console.log(buffer.toString());
                out.write(buffer.toString());
             }
        });
    }
});
相关推荐
"Wild dream"1 小时前
NodeJs内置的Npm
前端·npm·node.js
海参崴-1 小时前
深入剖析C语言结构体存储规则:内存对齐原理与实战详解
java·c语言·开发语言
南山乐只1 小时前
Java并发工具:synchronized演进,从JDK 1.6 锁升级到 JDK 24 重构
java·开发语言·后端·职场和发展
无籽西瓜a1 小时前
【西瓜带你学设计模式 | 第十三期 - 组合模式】组合模式 —— 树形结构统一处理实现、优缺点与适用场景
java·后端·设计模式·组合模式·软件工程
翊谦10 小时前
Java Agent开发 Milvus 向量数据库安装
java·数据库·milvus
晓晓hh10 小时前
JavaSE学习——迭代器
java·开发语言·学习
查古穆10 小时前
栈-有效的括号
java·数据结构·算法
__土块__10 小时前
一次 Spring 事务传播机制源码走读:从误用 @Transactional 到理解嵌套事务的边界
spring·threadlocal·编程式事务·@transactional·事务传播·源码走读·requires_new
Java面试题总结10 小时前
Spring - Bean 生命周期
java·spring·rpc