likes
comments
collection
share

【node】Zlib

作者站长头像
站长
· 阅读数 33

node:zlib 模块提供了使用 Gzip、Deflate/Inflate、以及 Brotli 实现的压缩功能。

deflate 算法

DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。DEFLATE压缩与解代码可以在自由、通用的压缩库zlib上找到。常见的压缩算法如下:

  • zlib(RFC1950):一种格式,是对deflate进行了简单的封装,zlib = zlib头 + deflate编码的实际内容 + zlib尾
  • gzip(RFC1952):一种格式,也是对deflate进行的封装,gzip = gzip头 + deflate编码的实际内容 + gzip尾

LZ77算法

LZ77是一种基于字典的算法,它将长字符串(也称为短语)编码成短小的标记,用小标记代替字典中的短语,从而达到压缩的目的。也就是说,它通过用小的标记来代替数据中多次重复出现的长串方法来压缩数据。其处理的符号不一定是文本字符,可以是任意大小的符号。

使用

压缩

const { createGzip } = require('zlib');
const { pipeline } = require('stream');
const {
  createReadStream,
  createWriteStream
} = require('fs');

const gzip = createGzip();
const source = createReadStream('input.txt');
const destination = createWriteStream('input.txt.gz');

pipeline(source, gzip, destination, (err) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
});

// 或者,promise 化

const { promisify } = require('util');
const pipe = promisify(pipeline);

async function do_gzip(input, output) {
  const gzip = createGzip();
  const source = createReadStream(input);
  const destination = createWriteStream(output);
  await pipe(source, gzip, destination);
}

do_gzip('input.txt', 'input.txt.gz')
  .catch((err) => {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  });

解压

const { createGunzip } = require('zlib');
const { pipeline } = require('stream');
const {
  createReadStream,
  createWriteStream
} = require('fs');

const gzip = createGunzip();
const source = createReadStream('input.txt');
const destination = createWriteStream('input.txt.gz');

pipeline(source, gzip, destination, (err) => {
  if (err) {
    console.error('An error occurred:', err);
    process.exitCode = 1;
  }
});

Zlib属性和方法

MethodDescription
constantsReturns an object containing Zlib constants
createDeflate()Creates a Deflate object
createDeflateRaw()Creates a DeflateRaw object
createGunzip()Creates a Gunzip object
createGzip()Creates a Gzip object
createInflate()Creates a Inflate object
createInflateRaw()Creates a InflateRaw object
createUnzip()Creates a Unzip object
deflate()Compress a string or buffer, using Deflate
deflateSync()Compress a string or buffer, syncronously, using Deflate
deflateRaw()Compress a string or buffer, using DeflateRaw
deflateRawSync()Compress a string or buffer, syncronously, using DeflateRaw
gunzip()Compress a string or buffer, using Gunzip
gunzipSync()Compress a string or buffer, syncronously, using Gunzip
gzip()Compress a string or buffer, using Gzip
gzipSync()Compress a string or buffer, syncronously, using Gzip
inflate()Decompress a string or buffer, using Inflate
inflateSync()Decompress a string or buffer, syncronously, using Inflate
inflateRaw()Decompress a string or buffer, using InflateRaw
inflateRawSync()Decompress a string or buffer, syncronously, using InflateRaw
unzip()Decompress a string or buffer, using Unzip
unzipSync()Decompress a string or buffer, syncronously, using Unzip

内存使用的调整

对于基于 zlib 的流

从 zlib/zconf.h 开始,针对 Node.js 使用进行了修改:

deflate 的内存要求是(以字节为单位):

(1 << (windowBits + 2)) + (1 << (memLevel + 9))

即:windowBits 的 128K = 15 + memLevel 的 128K = 8(默认值)加上小对象的几千字节。

例如,要将默认内存要求从 256K 减少到 128K,应将选项设置为:

const options = { windowBits: 14, memLevel: 7 };

然而,这通常会降低压缩性能。

inflate 的内存要求是(以字节为单位)1 << windowBits。 也就是说,windowBits 的 32K = 15(默认值)加上小对象的几千字节。

这是对大小为 chunkSize 的单个内部输出平板缓冲区的补充,默认为 16K。

zlib 压缩的速度受 level 设置的影响最大。 更高的级别将导致更好的压缩,但需要更长的时间才能完成。 较低的级别将导致较少的压缩,但会更快。

一般来说,更大的内存使用选项意味着 Node.js 必须对 zlib 进行更少的调用,因为它能够在每个 write 操作上处理更多的数据。 所以,这是影响速度的另一个因素,以内存使用为代价。

参考文章