deflate
– DEFLATE 压缩 & 解压¶
该模块允许使用 DEFLATE 算法 (通常用于 zlib 库和 gzip 压缩器)对二进制数据进行压缩和解压缩。
可用性:
在 MicroPython v1.21 中添加。
解压缩: 通过
MICROPY_PY_DEFLATE
构建选项启用,默认情况下在具有 “extra features “ 级别或更高级别的移植版本上启用(大多数开发板)。压缩: 通过
MICROPY_PY_DEFLATE_COMPRESS
构建选项启用,默认情况下在具有 “full features” 级别或更高级别的移植版本上启用(通常这意味着您需要构建自己的固件以启用此功能)。
类¶
- class deflate.DeflateIO(stream, format=AUTO, wbits=0, close=False, /)¶
这个类可以用来包装一个 stream,它是任何 stream-like 对象,比如文件、套接字或流(包括
io.BytesIO
)。它本身是一个流,并实现了标准的read/readinto/write/close 方法。stream 必须是一个阻塞流。非阻塞流目前不受支持。
format 可以设置为下面定义的任何常量,默认为
AUTO
,对于解压缩,它将自动检测 gzip 或 zlib 流,对于压缩,它将生成一个原始流。wbits 参数设置了 DEFLATE 字典窗口大小的以 2 为底的对数。例如,将 *wbits*设置为
10
,将窗口大小设置为 1024 字节。有效值为5
到15
(包括)(对应窗口大小为 32 到 32k 字节)。如果 wbits 设置为
0
(默认值),则对于压缩,将使用 256 字节的窗口大小(就好像 wbits 设置为 8)。对于解压缩,它取决于格式:RAW
将使用 256 字节(对应 wbits 设置为 8)。ZLIB
(或检测到 zlib 的AUTO
)将使用 zlib 标头中的值。GZIP
(或检测到 gzip 的AUTO
)将使用 32 千字节(对应 wbits 设置为 15)。
查看下面关于窗口大小、zlib 和 gzip 流的 window size 注意事项,获取更多信息。
如果 close 设置为
True
,那么在关闭deflate.DeflateIO
流时将自动关闭底层流。如果您希望返回一个包装另一个流的deflate.DeflateIO
流,并且不希望调用者知道如何管理底层流,这是有用的。如果启用了压缩,给定的
deflate.DeflateIO
实例支持读和写。例如,可以包装一个双向流(如套接字),这样就可以在两个方向上进行压缩/解压缩。
常量¶
示例¶
deflate.DeflateIO
的典型用例是从存储中读取或写入压缩文件:
import deflate
# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
with open("data.gz", "wb") as f:
with deflate.DeflateIO(f, deflate.ZLIB) as d:
# Use d.write(...) etc
# Reading a zlib-compressed stream (auto-detect window size).
with open("data.z", "rb") as f:
with deflate.DeflateIO(f, deflate.ZLIB) as d:
# Use d.read(), d.readinto(), etc.
因为 deflate.DeflateIO
是一个流,所以它可以与 json.dump()
和 json.load()
(以及任何其他可以使用流的地方)一起使用:
import deflate, json
# Write a dictionary as JSON in gzip format, with a
# small (64 byte) window size.
config = { ... }
with open("config.gz", "wb") as f:
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
json.dump(config, f)
# Read back that dictionary.
with open("config.gz", "rb") as f:
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
config = json.load(f)
如果您的源数据不是流格式,可以使用 io.BytesIO
将其转换为适合与 deflate.DeflateIO
: 一起使用的流:
import deflate, io
# Decompress a bytes/bytearray value.
compressed_data = get_data_z()
with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d:
decompressed_data = d.read()
# Compress a bytes/bytearray value.
uncompressed_data = get_data()
stream = io.BytesIO()
with deflate.DeflateIO(stream, deflate.ZLIB) as d:
d.write(uncompressed_data)
compressed_data = stream.getvalue()
DEFLATE 窗口大小¶
窗口大小限制了(解)压缩器在流中可以引用的距离。增加窗口大小将提高压缩率,但会需要更多内存,并使压缩器变慢。
如果输入流被压缩到了给定的窗口大小,那么使用较小窗口大小的 DeflateIO
在解压缩过程中会在中途失败,抛出 OSError
,但仅当后向引用实际上超出了解压缩器的窗口大小时。这意味着可能可以使用较小的窗口大小解压缩。例如,如果原始未压缩数据比窗口大小短,则这显然是可能的。
解压缩¶
zlib 格式包括一个头,指定了用于压缩数据的窗口大小。这表示解压缩此流所需的最大窗口大小。如果此头值小于指定的 wbits 值(或 wbits 未设置),则将使用头值。
gzip 格式不在头中包括窗口大小,并假定所有 gzip 压缩器(例如 gzip
实用程序或 CPython 的 gzip.GzipFile
实现)使用 32kiB 的最大窗口大小。因此,如果 wbits 参数未设置,则解压缩器将使用 32 kiB 的窗口大小(对应 wbits 设置为 15)。这意味着为了能够解压缩任意 gzip 流,您必须至少有这么多 RAM 可用。如果您控制源数据,考虑使用 zlib 格式并使用较小的窗口大小。
原始格式没有头,因此不包括有关窗口大小的任何信息。如果未设置 wbits,则默认使用256 字节的窗口大小,这可能对于给定的流来说不够大。因此,建议如果使用原始格式,应始终明确设置 wbits。
压缩¶
对于压缩,MicroPython 将默认为所有格式使用 256 字节的窗口大小。这提供了合理的压缩量,内存使用量小,压缩时间快,并且生成的输出可以与任何解压缩器一起使用。