Python3实现zip分卷压缩

Python实现zip分卷压缩

使用 zipfile 库

查看 官方中文文档

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

折腾经过

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

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

如果想把单个大文件 test.zip -> 分卷文件 test.z01test.z02test.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 库不支持创建分卷文件了〒▽〒

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

原文地址:https://www.cnblogs.com/zaxtyson/p/11638471.html

时间: 2024-07-30 13:06:38

Python3实现zip分卷压缩的相关文章

linux下分卷压缩,合并解压的3种方法

我们上传东西的时候,由于文件过大而不能上传,或者不给上传,最明显的就是发邮件了,附件最大5M,有的10M.如果超过了就郁闷了.这个时候,如果能把压缩的东西,分割开来就比较爽了,windows下面我想大家知道怎么分割,利用winrar,winzip图型化设置压缩出来的块的大小.但是在linux下面有没有这样的方法了,linux下面有rar命令,有zip命令,windows下面这二种方式可以分割压缩,我想linux下面绝对也是可以的.下面是我尝试过程的记录: 一,rar分卷压缩和合并解压 rar -

linux下分卷压缩,从Linux下载大于4G文件到本地,并且在本地合并

背景:由于从linux上下载文件时如果大于4G,使用sz命令无法下载,所以需要将文件分卷压缩. 步骤: 1.将大文件压缩成1G的文件:cat mydata.zip | split -b 1G - mydata_20200302.zip. 其中mydata.zip为大文件名称,mydata_20200302.zip.为是拆分后文件的前缀,默认分拆后文件名称为mydata_20200302.zip.aa,ab,ac....类推 2.下载每个2G的压缩文件到本地:sz mydata_20200302.

java.util.zip.ZipOutputStream压缩无乱码(原创)

package io; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.zip.Adler32; import java.u

linux 下 zip unzip压缩与解压

注:*压缩成限.zip格式文件 常用解压缩: [[email protected] test]# unzip -o test.zip -d tmp/ 将压缩文件test.zip在指定目录tmp下解压缩,如果已有相同的文件存在,要求unzip命令覆盖原先的文件. 常用压缩: [[email protected] test]# zip -r test.zip ./* 将当前目录下的所有文件和文件夹全部压缩成test.zip文件,-r表示递归压缩子目录下所有文件. 以下命令均在/home目录下操作cd

Java对zip格式压缩和解压缩

Java对zip格式压缩和解压缩 通过使用java的相关类可以实现对文件或文件夹的压缩,以及对压缩文件的解压. 1.1 ZIP和GZIP的区别 gzip是一种文件压缩工具(或该压缩工具产生的压缩文件格式),它的设计目标是处理单个的文件.gzip在压缩文件中的数据时使用的就是zlib.为了保存与文件属性有关的信息,gzip需要在压缩文件(*.gz)中保存更多的头信息内容,而zlib不用考虑这一点.但gzip只适用于单个文件,所以我们在UNIX/Linux上经常看到的压缩包后缀都是*.tar.gz或

linux tar.gz zip 解压缩 压缩命令

tar负责打包,gzip负责压缩 tar-c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的参数是根据需要在压缩或解压档案时可选的. -z:有gzip属性的-j:有bz2属性的-Z:有compress属性的-v:显示所有过程-O:将文件解开到标准输出 下面的参数-f是必须的-f: 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名.# tar -

WinRAR文件分卷压缩具体使用方法图文教程

WinRAR是很多电脑用户都在使用的一款文件压缩软件,今天,我们就一起来认识一下WinRAR的一个非常使用的功能:文件分卷压缩功能.那么,什么是文件分卷压缩功能,文件分卷压缩有什么用呢?文件分卷压缩有什么使用技巧呢?相信您在看完今天的教程之后就会明白的! 1.文件分卷压缩的方法 首先,选择你要分卷压缩的文件,点鼠标右键选"添加到压缩文件",如下图: 接着,在左下角的压缩方式中选择"最好",如下图,然后,在左下角的压缩分卷大小里选择压缩的分卷大小,或者自己设定您要的单

linux下tar、zip等压缩、解压命令

.tar解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)---------------------------------------------.gz解压1:gunzip FileName.gz解压2:gzip -d FileName.gz压缩:gzip FileName.tar.gz 和 .tgz解压:tar zxvf FileName.tar.gz压缩:tar zcvf FileName.tar.g

Dream------Java--ant zip 对压缩文件进行指定位置的修改

ant zip 对压缩文件进行指定位置的修改 实现功能: 对2中文件进行修改: 需求: 在XX文件中,从二进制流的200字节位置开始,往后的30位字节数量.插入一个值 由于涉及到公司内部,不方便写太多. 代码: import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; impo