詳解Python如何實現壓縮與解壓縮數據
楔子
當數據量大的時候,自然而然想到的就是對數據進行壓縮,下面來看看 Python 如何壓縮數據。這里主要介紹三個模塊,分別是 zlib、bz2、gzip,它們都是內置的,直接導入即可,不需要額外安裝。
那么下面就開始吧。
zlib 模塊
看一下 zlib 模塊的用法。
import zlib original_data = b"komeiji satori is a cute girl" print(len(original_data)) """ 29 """ # 對數據進行壓縮 compressed_data = zlib.compress(original_data) print(len(compressed_data)) """ 37 """ # 我們看到當數據量很小的時候,壓縮之后反而會增大 # 對數據進行解壓 print( zlib.decompress(compressed_data) == original_data ) """ True """
在壓縮的時候還可以指定壓縮級別:
import zlib original_data = b"komeiji satori is a cute girl" * 1024 # 壓縮級別 0 ~ 9,值越大,壓縮級別越高,默認壓縮級別為 6 for i in range(0, 10): compressed_data = zlib.compress(original_data, i) print(f"壓縮前數據長度: {len(original_data)}, " f"壓縮后數據長度: {len(compressed_data)}") """ 壓縮前數據長度: 29696, 壓縮后數據長度: 29707 壓縮前數據長度: 29696, 壓縮后數據長度: 245 壓縮前數據長度: 29696, 壓縮后數據長度: 245 壓縮前數據長度: 29696, 壓縮后數據長度: 245 壓縮前數據長度: 29696, 壓縮后數據長度: 122 壓縮前數據長度: 29696, 壓縮后數據長度: 122 壓縮前數據長度: 29696, 壓縮后數據長度: 122 壓縮前數據長度: 29696, 壓縮后數據長度: 122 壓縮前數據長度: 29696, 壓縮后數據長度: 122 壓縮前數據長度: 29696, 壓縮后數據長度: 122 """
壓縮級別越高,速度越慢,但壓縮之后的數據體積也越小。
如果你要壓縮的數據過大,那么還可以采用增量壓縮。
from io import BytesIO import zlib # 用 buffer 模擬大文件 original_data = b"komeiji satori is a cute girl" * 1024 buffer = BytesIO() buffer.write(original_data) buffer.seek(0) # 創(chuàng)建壓縮器,壓縮等級為 5 compressor = zlib.compressobj(5) # 每次讀取 1024 字節(jié),進行壓縮 while (data := buffer.read(1024)) != b"": compressor.compress(data) # 循環(huán)結束之后,壓縮結束,調用 flush 方法拿到壓縮數據 compressed_data = compressor.flush() # 這里我們進行解壓,然后對比一下,看看和原始數據是否相等 # 注意:zlib 壓縮之后是有一個頭部信息的,否則會認為數據不是 zlib 壓縮格式 # 但是增量壓縮會將頭部信息給去掉,所以解壓的時候還要手動加上 # 這個頭部信息是 b"x\x9c",轉成十六進制就是 "789c" decompressed_data = zlib.decompress(b"x\x9c" + compressed_data) print(original_data == decompressed_data) """ True """
壓縮數據還可以和原始數據混在一起,舉個例子:
import zlib original_data = b"komeiji satori is a cute girl" * 1024 compressed_data = zlib.compress(original_data) combined_data = compressed_data + original_data # 創(chuàng)建一個解壓縮器 decompressor = zlib.decompressobj() # 對 combined_data 進行解壓,只會得到對 compressed_data 解壓之后的數據 # 由于 zlib 會在壓縮數據前面加上一個頭部信息,所以 combined_data 要求必須是壓縮數據在前 decompressed_data = decompressor.decompress(combined_data) # 和原始數據是相等的 print(decompressed_data == original_data) """ True """ # 還可以拿到未解壓的數據,顯然也是原始數據 print(decompressor.unused_data == original_data) """ True """
當然,zlib 還支持驗證數據完整性。
import zlib original_data = b"komeiji satori is a cute girl" * 1024 # 計算 Adler-32 校驗和 print(zlib.adler32(original_data)) """ 4170046071 """ # 計算 CRC-32 校驗和 print(zlib.crc32(original_data)) """ 2627291461 """
以上就是 zlib 模塊的用法。
bz2 模塊
bz2 模塊和 zlib 的用法非常類似:
import bz2 original_data = b"komeiji satori is a cute girl" * 1024 # 也可以指定壓縮等級,范圍 1 ~ 9,注意:zlib 是 0 ~ 9 compressed_data = bz2.compress(original_data, 5) print(len(original_data)) """ 29696 """ print(len(compressed_data)) """ 103 """ print(bz2.decompress(compressed_data) == original_data) """ True """
也可以增量壓縮:
from io import BytesIO import bz2 original_data = b"komeiji satori is a cute girl" * 1024 buffer = BytesIO() buffer.write(original_data) buffer.seek(0) # 創(chuàng)建壓縮器,壓縮等級為 5 compressor = bz2.BZ2Compressor(5) while (data := buffer.read(1024)) != b"": compressor.compress(data) compressed_data = compressor.flush() # 這里不需要額外補充頭部信息 decompressed_data = bz2.decompress(compressed_data) print(original_data == decompressed_data) """ True """
也可以同時包含壓縮數據和未壓縮數據:
import bz2 original_data = b"komeiji satori is a cute girl" * 1024 compressed_data = bz2.compress(original_data) combined_data = compressed_data + original_data # 創(chuàng)建一個解壓縮器 decompressor = bz2.BZ2Decompressor() decompressed_data = decompressor.decompress(combined_data) # 和原始數據是相等的 print(decompressed_data == original_data) # True # 還可以拿到未解壓的數據,顯然也是原始數據 print(decompressor.unused_data == original_data) # True # 同樣要求壓縮數據在前
相比 zlib,bz2 還可以讀寫文件:
import os import bz2 original_data = b"komeiji satori is a cute girl" * 1024 # 寫入文件 with bz2.open("1.bz2", "wb", compresslevel=9) as f: f.write(original_data) # 讀取文件,判斷兩者是否相等 with bz2.open("1.bz2", "rb", compresslevel=9) as f: print(f.read() == original_data) # True os.unlink("1.bz2")
當然我們使用內置函數 open 打開文件,然后手動寫入壓縮數據或者讀取數據再手動解壓,也是可以的。
gzip 模塊
首先 gzip 只有全量壓縮,沒有增量壓縮。
import gzip original_data = b"komeiji satori is a cute girl" * 1024 # 也可以指定壓縮等級,范圍 0 ~ 9 compressed_data = gzip.compress(original_data, 5) print(len(original_data)) """ 29696 """ print(len(compressed_data)) """ 134 """ print(gzip.decompress(compressed_data) == original_data) """ True """
還可以調用 gzip.open 函數:
import os import gzip original_data = b"komeiji satori is a cute girl" * 1024 # 寫入文件 with gzip.open("1.gz", "wb", compresslevel=9) as f: f.write(original_data) # 讀取文件,判斷兩者是否相等 with gzip.open("1.gz", "rb", compresslevel=9) as f: print(f.read() == original_data) # """ True """ os.unlink("1.gz")
小結
以上就是 Python 壓縮數據所使用的三個模塊,之間是比較相似的。另外再補充一點,一般將數據壓縮之后,會轉成 16 進制進行傳輸,舉個例子:
import binascii import gzip original_data = b"komeiji satori" compressed_data = gzip.compress(original_data, 5) # 轉成 16 進制 hex_data = binascii.hexlify(compressed_data) print( binascii.unhexlify(hex_data) == compressed_data ) # True
還是比較簡單的。
以上就是詳解Python如何實現壓縮與解壓縮數據的詳細內容,更多關于Python壓縮與解壓縮數據的資料請關注腳本之家其它相關文章!
相關文章
Python數據分析matplotlib設置多個子圖的間距方法
今天小編就為大家分享一篇Python數據分析matplotlib設置多個子圖的間距方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08有關Tensorflow梯度下降常用的優(yōu)化方法分享
今天小編就為大家分享一篇有關Tensorflow梯度下降常用的優(yōu)化方法分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02