Python3实现zip分卷压缩过程解析


Posted in Python onOctober 09, 2019

使用zipfile库

查看 官方中文文档

利用 Python 压缩 ZIP 文件,我们第一反应是使用 zipfile 库,然而,它的官方文档中却明确标注“此模块目前不能处理分卷 ZIP 文件”,(⊙?⊙)

折腾经过

翻遍了Google、CSDN、Stackoverflow等平台均未找到解决方案,最靠谱的是调用外部解压程序实现分卷压缩的功能。但是,如何不依靠外部程序实现这个功能呢??

于是乎,只能自己慢慢造轮子。看着 ZIP 格式开发商留下的文档 ZIP File Format Specification,头疼啊(;´д`)。于是我拿着 WinHex 开始16进制一个一个文件对比 WinRar 创建的分卷压缩和单个 zip 文件的差异。最后还真的整出来了( ̄? ̄)"

Python3实现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。

Python3的代码实现

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)   # 输出分卷压缩文件的路径

缺点

该方法创建分卷压缩的时候,需要先在磁盘创建一个临时压缩包,然后将其拆分,实际上会对磁盘写入两次,这就浪费了时间。

当然,我尝试使用 ByteIO 进行字节流的压缩,但是这种方式需要先把文件读入内存,对于超级大的文件,这是不现实的,分分钟内存爆炸。

然后,我尝试使用 io.pipe 的管道来处理,而 zipfile 压缩需要提供一个 file 或 file-like 对象,这个对象必须实现 seek() 和 tell() 方法来回去写入文件头信息,然而管道流没办法seek回去修改数据。这里,参考了Python zipfile + os.pipe()探索记,屏蔽了 seek() 和 tell() 函数。但是,后面我分卷时需要指定读取的字节数,这就需要这两个函数。。。我大概知道为什么 zipfile 库不支持创建分卷文件了???

这个库的作者也没少掉头发。。。现在就将就一下,这样用着吧。。。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用PyGame模块播放声音的方法
May 20 Python
Python实现删除文件中含“指定内容”的行示例
Jun 09 Python
Django框架教程之正则表达式URL误区详解
Jan 28 Python
解析python的局部变量和全局变量
Aug 15 Python
python连接、操作mongodb数据库的方法实例详解
Sep 11 Python
python修改FTP服务器上的文件名
Sep 11 Python
Python3.5 win10环境下导入kera/tensorflow报错的解决方法
Dec 19 Python
Keras搭建自编码器操作
Jul 03 Python
python中的垃圾回收(GC)机制
Sep 21 Python
python实现录音功能(可随时停止录音)
Oct 26 Python
pytorch常用数据类型所占字节数对照表一览
May 17 Python
使用Python开发冰球小游戏
Apr 30 Python
基于Python新建用户并产生随机密码过程解析
Oct 08 #Python
Python小程序 控制鼠标循环点击代码实例
Oct 08 #Python
Python3 无重复字符的最长子串的实现
Oct 08 #Python
解决python 读取excel时 日期变成数字并加.0的问题
Oct 08 #Python
python3.7 openpyxl 删除指定一列或者一行的代码
Oct 08 #Python
python实现的按要求生成手机号功能示例
Oct 08 #Python
python集合的创建、添加及删除操作示例
Oct 08 #Python
You might like
PHP 编程请选择正确的文本编辑软件
2006/12/21 PHP
PHP 操作文件的一些FAQ总结
2009/02/12 PHP
Symfony2框架创建项目与模板设置实例详解
2016/03/17 PHP
php微信开发之百度天气预报
2016/11/18 PHP
PHP构造二叉树算法示例
2017/06/21 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
Laravel框架Eloquent ORM修改数据操作示例
2019/12/03 PHP
List Installed Software Features
2007/06/11 Javascript
form表单action提交的js部分与html部分
2014/01/07 Javascript
jquery 页眉单行信息滚动显示实现思路及代码
2014/06/26 Javascript
jquery使用each方法遍历json格式数据实例
2015/05/18 Javascript
详解JavaScript中的blink()方法的使用
2015/06/08 Javascript
关于JSON与JSONP简单总结
2016/08/16 Javascript
js遍历map javaScript遍历map的简单实现
2016/08/26 Javascript
jQuery实现获取元素索引值index的方法
2016/09/18 Javascript
js获取元素的标签名实现方法
2016/10/08 Javascript
JS IOS/iPhone的Safari浏览器不兼容Javascript中的Date()问题如何解决
2016/11/11 Javascript
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
2017/06/02 jQuery
js对象实例详解(JavaScript对象深度剖析,深度理解js对象)
2017/09/21 Javascript
vue.js实现格式化时间并每秒更新显示功能示例
2018/07/07 Javascript
vue router 跳转后回到顶部的实例
2018/08/31 Javascript
layer弹出层显示在top顶层的方法
2019/09/11 Javascript
Vue.js实现立体计算器
2020/02/22 Javascript
基于Python和Scikit-Learn的机器学习探索
2017/10/16 Python
Python使用add_subplot与subplot画子图操作示例
2018/06/01 Python
python将txt文件读入为np.array的方法
2018/10/30 Python
Python向excel中写入数据的方法
2019/05/05 Python
Python图像处理库PIL的ImageGrab模块介绍详解
2020/02/26 Python
如何写python的配置文件
2020/06/07 Python
浅谈Python 钉钉报警必备知识系统讲解
2020/08/17 Python
详解Python中的文件操作
2021/01/14 Python
硕士研究生就业推荐信
2014/05/18 职场文书
小学优秀教师材料
2014/12/15 职场文书
2016年七夕爱情寄语
2015/12/04 职场文书
机关干部作风整顿心得体会
2016/01/22 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书