deflate --- nén & giải nén deflate¶
Mô-đun này cho phép nén và giải nén dữ liệu nhị phân bằng thuật toán DEFLATE (thường dùng trong thư viện zlib và công cụ nén gzip). Được thêm vào MicroPython v1.21.
Tính khả dụng trên các board được OpenMV hỗ trợ:
Board |
Giải nén |
Nén |
|---|---|---|
OpenMV Cam N6 |
Có |
Không |
OpenMV AE3 |
Có |
Có |
OpenMV Cam RT1062 |
Có |
Có |
OpenMV Cam Pure Thermal |
Có |
Không |
OpenMV Cam M4 |
Có |
Không |
OpenMV Cam M7 |
Có |
Không |
OpenMV Cam H7 |
Có |
Không |
OpenMV Cam H7 Plus |
Có |
Không |
Arduino Giga |
Có |
Không |
Arduino Portenta H7 |
Có |
Không |
Arduino Nicla Vision |
Có |
Không |
Arduino Nano 33 BLE Sense |
Có |
Không |
Arduino Nano RP2040 Connect |
Có |
Không |
Lớp¶
- class deflate.DeflateIO(stream: Any, format: int = AUTO, wbits: int = 0, close: bool = False, /)¶
Lớp này có thể dùng để bọc một stream, là bất kỳ đối tượng stream-like nào như file, socket, hoặc stream (bao gồm
io.BytesIO). Bản thân nó là một stream và triển khai các phương thức chuẩn read/readinto/write/close.stream phải là stream chặn. Stream không chặn hiện chưa được hỗ trợ.
Tham số format có thể được đặt thành bất kỳ hằng số nào được định nghĩa bên dưới, mặc định là
AUTO: khi giải nén sẽ tự phát hiện stream gzip hoặc zlib, khi nén sẽ tạo ra stream thô.Tham số wbits đặt logarit cơ số 2 của kích thước cửa sổ từ điển DEFLATE. Ví dụ, đặt wbits thành
10sẽ đặt kích thước cửa sổ là 1024 byte. Các giá trị hợp lệ là5đến15(tương ứng kích thước cửa sổ từ 32 đến 32k byte).Nếu wbits được đặt thành
0(mặc định), thì khi nén sẽ dùng kích thước cửa sổ 256 byte (như thể wbits được đặt thành 8). Khi giải nén, điều này phụ thuộc vào định dạng:RAWsẽ dùng 256 byte (tương ứng wbits đặt thành 8).ZLIB(hoặcAUTOkhi phát hiện zlib) sẽ dùng giá trị từ header zlib.GZIP(hoặcAUTOkhi phát hiện gzip) sẽ dùng 32 kilobyte (tương ứng wbits đặt thành 15).
Xem ghi chú kích thước cửa sổ bên dưới để biết thêm thông tin về kích thước cửa sổ, zlib và stream gzip.
Nếu close được đặt thành
Truethì stream bên dưới sẽ được đóng tự động khi streamdeflate.DeflateIOđược đóng. Điều này hữu ích khi bạn muốn trả về streamdeflate.DeflateIObọc một stream khác mà không cần người gọi phải biết cách quản lý stream bên dưới.Nếu nén được bật, một thực thể
deflate.DeflateIOnhất định hỗ trợ cả đọc và ghi. Ví dụ, một stream hai chiều như socket có thể được bọc, cho phép nén/giải nén theo cả hai chiều.
Hằng số¶
Bốn hằng số format chọn khung bao quanh luồng bit deflate thô.
- deflate.AUTO: int¶
Để giải nén, tự động phát hiện định dạng đầu vào bằng cách kiểm tra các byte đầu tiên của stream (zlib hoặc gzip). Để nén, tạo ra stream deflate thô không có header hoặc trailer (tương đương
RAW).
- deflate.RAW: int¶
Stream deflate thô (không có header, không có trailer, không có checksum). Vì stream không chứa metadata, bộ giải nén không thể khôi phục kích thước cửa sổ từ dữ liệu, vì vậy wbits nên được đặt rõ ràng khi giải nén -- nếu không cửa sổ mặc định 256 byte có thể quá nhỏ.
- deflate.ZLIB: int¶
Stream deflate được bọc bởi zlib như định nghĩa trong RFC 1950: header 2 byte ghi lại kích thước cửa sổ, payload deflate, và checksum Adler-32 ở cuối. Nhỏ gọn và tự mô tả; phù hợp tốt cho ứng dụng nhúng.
- deflate.GZIP: int¶
Stream deflate được bọc bởi gzip như định nghĩa trong RFC 1952: header với metadata tên file/timestamp tùy chọn, payload deflate, và CRC-32 cộng độ dài chưa nén ở cuối. Đây là định dạng được tạo ra bởi công cụ dòng lệnh
gzipvà bởigzip.GzipFile. Header không ghi kích thước cửa sổ, vì vậy bộ giải nén phải giả định 32 KiB trừ khi wbits được đặt.
Ví dụ¶
Trường hợp sử dụng điển hình cho deflate.DeflateIO là đọc hoặc ghi file nén từ bộ nhớ:
import deflate
# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
with open("data.z", "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.
Vì deflate.DeflateIO là một stream, nó có thể dùng với json.dump() và json.load() (và bất kỳ nơi nào khác có thể dùng stream):
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)
Nếu dữ liệu nguồn không ở định dạng stream, bạn có thể dùng io.BytesIO để chuyển nó thành stream phù hợp để dùng với 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()
Kích thước cửa sổ Deflate¶
Kích thước cửa sổ giới hạn khoảng cách trong stream mà bộ (giải) nén có thể tham chiếu ngược lại. Tăng kích thước cửa sổ sẽ cải thiện khả năng nén, nhưng sẽ yêu cầu nhiều bộ nhớ hơn và làm bộ nén chậm hơn.
Nếu một stream đầu vào được nén với một kích thước cửa sổ nhất định, thì DeflateIO dùng kích thước cửa sổ nhỏ hơn sẽ thất bại giữa chừng trong quá trình giải nén với OSError, nhưng chỉ khi một tham chiếu ngược thực sự tham chiếu xa hơn kích thước cửa sổ của bộ giải nén. Điều này có nghĩa là có thể giải nén với kích thước cửa sổ nhỏ hơn. Ví dụ, điều này hiển nhiên đúng nếu dữ liệu gốc chưa nén ngắn hơn kích thước cửa sổ.
Giải nén¶
Định dạng zlib bao gồm một header xác định kích thước cửa sổ được dùng để nén dữ liệu. Điều này chỉ ra kích thước cửa sổ tối đa cần thiết để giải nén stream này. Nếu giá trị header này nhỏ hơn giá trị wbits được chỉ định (hoặc nếu wbits chưa được đặt), thì giá trị header sẽ được dùng.
Định dạng gzip không bao gồm kích thước cửa sổ trong header, và giả định rằng tất cả bộ nén gzip (ví dụ: công cụ gzip, hoặc triển khai của CPython cho gzip.GzipFile) dùng kích thước cửa sổ tối đa là 32kiB. Vì lý do này, nếu tham số wbits không được đặt, bộ giải nén sẽ dùng kích thước cửa sổ 32 kiB (tương ứng wbits đặt thành 15). Điều này có nghĩa là để có thể giải nén một stream gzip tùy ý, bạn phải có ít nhất dung lượng RAM này. Nếu bạn kiểm soát dữ liệu nguồn, hãy cân nhắc sử dụng định dạng zlib với kích thước cửa sổ nhỏ hơn.
Định dạng thô không có header và do đó không bao gồm bất kỳ thông tin nào về kích thước cửa sổ. Nếu wbits không được đặt, nó sẽ mặc định là kích thước cửa sổ 256 byte, có thể không đủ lớn cho một stream nhất định. Do đó, nên luôn đặt wbits một cách rõ ràng khi dùng định dạng thô.
Nén¶
Để nén, MicroPython mặc định kích thước cửa sổ là 256 byte cho tất cả các định dạng. Điều này cung cấp lượng nén hợp lý với mức sử dụng bộ nhớ tối thiểu và thời gian nén nhanh, và sẽ tạo ra đầu ra hoạt động với bất kỳ bộ giải nén nào.