天天看點

python實作zip分卷壓縮與解壓

1. python實作zip分卷壓縮

WinHex 開始16進制一個一個檔案對比 WinRar 建立的分卷壓縮和單個 zip 檔案的差異。

python實作zip分卷壓縮與解壓

如果想把單個大檔案 ​

​test.zip​

​​ -> 分卷檔案 ​

​test.z01​

​​、​

​test.z02​

​​、​

​test.zip​

首先,在建立的第一個分卷檔案 ​

​test.z01​

​​的前面加上 ​

​\x50\x4b\x07\x08​

​​ 這個是分卷壓縮的檔案頭(header),占4個位元組。其實單個壓縮檔案本身 header 就有這個了,而分卷壓縮的需要兩個emmm。之後便是從單個大壓縮檔案檔案​

​test.zip​

​​中讀取 "一個分卷大小 -4 個位元組"的資料,寫入​

​test.z01​

​​中,如何接着讀取一個分卷大小的資料,寫入​

​test.z02​

​​,以此類推,最後一個分卷檔案名也是​

​test.zip​

1.1 代碼如下:

import os
import zipfile


def zip_by_volume(file_path, block_size):
    """zip檔案分卷壓縮"""
    file_size = os.path.getsize(file_path)  # 檔案位元組數
    path, file_name = os.path.split(file_path)  # 除去檔案名以外的path,檔案名
    suffix = file_name.split('.')[-1]  # 檔案字尾名
    # 添加到臨時壓縮檔案
    zip_file = file_path + '.zip'
    with zipfile.ZipFile(zip_file, 'w') as zf:
        zf.write(file_path, arcname=file_name)
    # 小于分卷尺寸則直接傳回壓縮檔案路徑
    if file_size <= block_size:
        return zip_file
    else:
        fp = open(zip_file, 'rb')
        count = file_size // block_size + 1
        # 建立分卷壓縮檔案的儲存路徑
        save_dir = path + os.sep + file_name + '_split'
        if os.path.exists(save_dir):
            from shutil import rmtree
            rmtree(save_dir)
        os.mkdir(save_dir)
        # 拆分壓縮包為分卷檔案
        for i in range(1, count + 1):
            _suffix = 'z{:0>2}'.format(i) if i != count else 'zip'
            name = save_dir + os.sep + file_name.replace(str(suffix), _suffix)
            f = open(name, 'wb+')
            if i == 1:
                f.write(b'\x50\x4b\x07\x08')  # 添加分卷壓縮header(4位元組)
                f.write(fp.read(block_size - 4))
            else:
                f.write(fp.read(block_size))
        fp.close()
        os.remove(zip_file)     # 删除臨時的 zip 檔案   
        return save_dir


if __name__ == '__main__':
    file = r"D:\Downloads\1.mp4"        # 原始檔案
    volume_size = 1024 * 1024 * 100  # 分卷大小 100MB
    path = zip_by_volume(file, volume_size)
    print(path)     # 輸出分卷壓縮檔案的路徑      

 1.2 缺點:

2.解壓