Lua如何在内存中使用gzip对字符串进行压缩(不是zlib)?

给定一个字符串,如何在内存中使用gzip进行压缩?我正在使用Lua。


这听起来是一个简单的问题,但是有一个庞大的库列表。到目前为止,我尝试过的所有库要么已经停止开发,要么只能生成zlib压缩的字符串。在我的使用情况下,我需要gzip压缩,因为接受者需要这样。

作为一个测试,如果你将压缩后的字符串转储到一个文件,zcat 应该能够解压它。

我正在使用OpenResty,所以任何Lua库都可以使用。

(到目前为止,我唯一得到的解决方案是将字符串转储到文件中,调用 os.execute("gzip /tmp/example.txt"),然后将其读回来。不幸的是,这不是一个实际的解决方案。)

点赞
用户783510
用户783510

原来 zlib 与 gzip 差别不大,区别在于 gzip 增加了一个 header。

通过使用 lua-zlib,你可以获取这个 header,代码如下:

local zlib = require "zlib"

-- input:  string
-- output: string compressed with gzip
function compress(str)
   local level = 5
   local windowSize = 15+16
   return zlib.deflate(level, windowSize)(str, "finish")
end

解释:

  • deflate 函数的第二个参数是窗口大小,确保写入 gzip header。如果省略这个参数,将得到一个 zlib 压缩的字符串。
  • level 是 gzip 压缩级别(1 最低,9 最高)

以下是 deflate 函数的文档(来源:lua-zlib documentation):

function stream = zlib.deflate([ int compression_level ], [ int window_size ])

如果未提供 compression_level,则使用 Z_DEFAULT_COMPRESSION(6)。
compression level 是 1-9 的数字,其中 zlib.BEST_SPEED 是 1,zlib.BEST_COMPRESSION 是 9。

返回一个“stream”函数,该函数会压缩(或缩小)所有传入的字符串。具体使用方法如下:

string deflated, bool eof, int bytes_in, int bytes_out =
        stream(string input [, 'sync' | 'full' | 'finish'])

    接受输入并缩小并返回其中一部分,可选地强制刷新。

    “sync”刷新将强制将所有挂起的输出刷新到返回值并将输出对齐到字节边界,以便解压缩器可以获取到迄今为止可用的所有输入数据。刷新可能会降低某些压缩算法的压缩率,因此仅在必要时使用。

    “full”刷新将像“sync”一样刷新所有输出,并重置压缩状态,以便在以前的压缩数据已经损坏或需要随机访问时从此处重新启动解压缩。过于频繁地使用 Z_FULL_FLUSH 可会严重降低压缩率。

    “finish”刷新将强制处理所有挂起的输出,并导致流变得无法使用。任何将来尝试打印空字符串以外的内容的尝试都将导致以 IllegalState 开头的错误。

    如果指定了“finish”,则 eof 结果为 true,否则为 false。

    bytes_in 是传递给 stream 的输入字节数,bytes_out 是 deflated 字符串块中返回的字节数。
2017-07-20 17:28:47