Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Python

Nén bằng thuật toán LZMA trong Python (lzma)


Thuật toán Lempel–Ziv–Markov chain algorithm (LZMA) thực hiện nén dữ liệu không mất mát (lossless) bằng sơ đồ nén từ điển (dictionary compression scheme) với tỷ lệ nén cao hơn các thuật toán nén khác. Mô-đun lzma của Python bao gồm các lớp và hàm tiện ích cho nén và giải nén dữ liệu với thuật toán LZMA.

Mặc dù chức năng trong mô-đun này tương tự mô-đun bz2, lớp LZMAFile không an toàn luồng (thread-safe) như so với lớp BZ2File.

Ở đây cũng vậy, hàm open() trong mô-đun lzma là cách dễ nhất để mở đối tượng file nén LZMA.

open()

Hàm này mở file nén LZMA và trả về đối tượng file. Hàm yêu cầu hai tham số chính - tên file và mode. Tham số mode mặc định là "rb" nhưng có thể nhận bất kỳ giá trị nào sau:

chế độ nhị phân - "r", "rb", "w", "wb", "x", "xb", "a" hoặc "ab"
chế độ văn bản - "rt", "wt", "xt", hoặc "at"

compress()

Hàm này nén dữ liệu cho trước dùng thuật toán LZMA và trả về đối tượng byte. Hàm này có thể có đối số format tùy chọn quyết định định dạng container. Giá trị có thể là FORMAT_XZ (mặc định) và FORMAT_ALONE.

decompress()

Hàm này giải nén dữ liệu và trả về đối tượng byte không nén.

Các hàm trên được dùng trong các ví dụ sau. Để ghi dữ liệu nén LZMA vào file:

>>> import lzma
>>> data = b"Welcome to TutorialsPoint"
>>> f = lzma.open("test.xz", "wb")
>>> f.write(data)
>>> f.close()

Một file test.xz sẽ được tạo trong thư mục làm việc hiện tại. Để lấy dữ liệu không nén từ file này dùng mã sau:

>>> import lzma
>>> f = lzma.open("test.xz", "rb")
>>> data = f.read()
>>> data
b'Welcome to TutorialsPoint'

Để thực hiện nén bằng API hướng đối tượng của mô-đun lzma, chúng ta phải dùng lớp LZMAFile.

LZMAFile()

Đây là constructor cho lớp LZMAFile. Nó yêu cầu file và mode được chỉ định. Đối tượng với mode 'w' hoặc 'wb' làm phương thức write() có sẵn cho nó.

write()

Phương thức này nén dữ liệu cho trước và ghi nó vào file bên dưới nó.

>>> data = b'Welcome to TutorialsPoint'
>>> obj = lzma.LZMAFile("test.xz", mode="wb")
>>> obj.write(data)
>>> obj.close()

File nén được đọc và dữ liệu không nén được truy xuất bởi phương thức read() của đối tượng LZMAFile được tạo với tham số mode='rb'.

read()

Phương thức này đọc dữ liệu từ file nén và trả về dữ liệu không nén.

>>> obj = lzma.LZMAFile("test.xz", mode="rb")
>>> data = obj.read()
>>> data
b'Welcome to TutorialsPoint'

Thuật toán LZMA cho phép ghi dữ liệu nén vào file đã mở sẵn. Trong ví dụ sau, test.txt được mở bình thường (bằng hàm tích hợp sẵn open()) ở mode 'wb' và một số văn bản được ghi vào nó. Sau đó, cùng file đó được dùng để ghi dữ liệu nén.

>>> f = open("test.txt", "wb")
>>> f.write(b"Hello world")
>>> fp = lzma.open(f, "wb")
>>> fp.write(b"Welcome to Python")
>>> f.write(b"Thank you")
>>> f.close()
>>> fp.flush()
>>> fp.close()

Khi mã trên được thực thi, test.txt xuất hiện trong thư mục hiện tại. Nó chứa hỗn hợp dữ liệu nén và không nén như sau:

Hello worldý7zXZ æÖ´F!t/å£Thank you

Giống như mô-đun bz2, mô-đun lzma cũng có lớp nén và giải nén tăng dần (incremental).

LZMACompressor()

Đây là constructor trả về đối tượng nén tăng dần. Nhiều khối (chunk) có thể được nén riêng lẻ và dữ liệu nối của chúng được ghi vào file.

compress()

Phương thức này nén dữ liệu cho trước và trả về đối tượng byte.

flush()

Phương thức này làm rỗng bộ đệm và trả về đối tượng byte.

Ví dụ sau nén một đối tượng danh sách dùng đối tượng nén tăng dần.

>>> data = [b'Hello World', b'How are you?', b'welcome to Python']
>>> obj = lzma.LZMACompressor()
>>> bindata = []
>>> for i in data:
...     bindata.append(obj.compress(i))
>>> bindata.append(obj.flush())
>>> bindata
[b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3', b'', b'', b"\x01\x00'Hello WorldHow are you?welcome to Python\x00\xf5\xc6\xc1d|\xf3\x8ey\x00\x01@(\xd4RJ\xe5\x1f\xb6\xf3}\x01\x00\x00\x00\x00\x04YZ"]

Mã trên xây dựng bindata như danh sách các biểu diễn byte nén của mỗi mục trong danh sách gốc. Để truy xuất dữ liệu không nén dùng đối tượng LZMADecompressor, dùng câu lệnh sau:

>>> obj = lzma.LZMADecompressor()
>>> binstr = b''.join(bindata)
>>> obj.decompress(binstr)
b'Hello WorldHow are you?welcome to Python'

Trong bài viết này, các lớp và hàm trong mô-đun lzma đã được giải thích với ví dụ.