WinHex 开始16进制一个一个文件对比 WinRar 创建的分卷压缩和单个 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
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(null, 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) # 输出分卷压缩文件的路径
该方法创建分卷压缩的时候,需要先在磁盘创建一个临时压缩包,然后将其拆分,实际上会对磁盘写入两次,这就浪费了时间。
当然,使用 ByteIO 进行字节流的压缩,但是这种方式需要先把文件读入内存,对于超级大的文件,这是不现实的,分分钟内存爆炸
到此这篇关于python实现zip分卷压缩的文章就介绍到这了,更多相关python zip分卷压缩内容请搜索插件窝以前的文章或继续浏览下面的相关文章希望大家以后多多支持插件窝!