我要学习

分割与合并文件

可移植地分割文件

示例:split.py

#!/usr/bin/env python
"""
将文件分割成很多部分,join.py将它们合并回去;
这是标准的Unix split命令行工具的一个可移植版本,因为它用Python写成,所以在Windows下也能工作和方便的修改;
因为它包装成一个函数,所以它的逻辑业务也可以由其他命令程序导入并重复使用。
"""

import sys
import os


def split(fromfile, todir, chunksize=1024 * 1024):
    if not os.path.exists(todir):
        os.mkdir(todir)
    else:
        input('即将删除{}下的所有内容,按回车键继续……'.format(todir))
        for eachfile in os.listdir(todir):
            os.remove(os.path.join(todir, eachfile))
    partsnum = 0
    infile = open(fromfile, 'rb')

    while True:
        chunk = infile.read(chunksize)

        if not chunk:
            break

        partsnum += 1

        filename = os.path.join(todir, 'part{:0>4}'.format(partsnum))
        part = open(filename, 'wb')
        part.write(chunk)
        part.close()

    infile.close()
    assert partsnum <= 9999, "文件过大"
    return partsnum


def command():
    if len(sys.argv) == 2 and (sys.argv[1] == '--help' or sys.argv[1] == '-h'):
        print('Use: ./split.py [file-to-split target-dir [chunksize]]')
    else:
        chunksize = 1024 * 1024

        if len(sys.argv) < 3:
            interact = True
            fromfile = input('请输出要分割的文件:')
            todir = 'splited_' + os.path.basename(fromfile)
            todir = input(
                '请输入存储分割后的文件的目录(回车后默认{}):'.format(todir)
            ) or todir
            chunksize = input('请输入分割后文件kb大小(回车后默认1024):') or 1024
            chunksize = int(chunksize) * 1024
        else:
            interact = False
            fromfile, todir = sys.argv[1: 3]
            if len(sys.argv) == 4:
                chunksize = int(sys.argv[3]) * 1024

        absfrom, absto = map(os.path.abspath, [fromfile, todir])
        print('将{}分割到{}中,每个文件{}kb'.format(absfrom, absto, chunksize / 1024))

        try:
            partsnum = split(fromfile, todir, chunksize=chunksize)
        except Exception:
            print('分割失败')
            print(sys.exc_info()[0], sys.exc_info()[1])
        else:
            print('分隔成功:{}个分割文件在{}中'.format(partsnum, absto))
        if interact:
            input('按回车键退出……')


if __name__ == '__main__':
    command()

输出:split.py

$ ./split.py 
请输出要分割的文件:bigext_tree.py
请输入存储分割后的文件的目录(回车后默认splited_bigext_tree.py):
请输入分割后文件kb大小(回车后默认1024):1
将/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/bigext_tree.py分割到/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/splited_bigext_tree.py中,每个文件1.0kb
分隔成功:3个分割文件在/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/splited_bigext_tree.py中
按回车键退出……
$ ./split.py bigpy_path.py path1
将/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/bigpy_path.py分割到/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/path1中,每个文件1024.0kb
分隔成功:1个分割文件在/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/path1中
$ ./split.py bigpy_path.py path2 1
将/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/bigpy_path.py分割到/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/path2中,每个文件1.0kb
分隔成功:3个分割文件在/media/beacherhou/Coding/code_obsidian_知识库/python-programming---markdown-notes/my_PP4E/system/filetools/path2中
$ ls splited_bigext_tree.py/
part0001  part0002  part0003
$ ls path1/
part0001
$ ls path2/
part0001  part0002  part0003

可移植地合并文件

示例:join.py

#!/usr/bin/env python
"""
合并split.py创建的目录下的所有分割文件以重建文件。
大概相当于Unix下的cat fromdir/* > tofile命令,
不过可移植性和可配置性更好,
并且将合并操作作为可以重复使用的函数。
依赖文件名的排序顺序:长度必须一致。
可以进一步拓展为分割/合并,弹出Tkinter文件选择器。
"""

import os
import sys


def join(fromdir, tofile, readsize=1024):
    output = open(tofile, 'wb')
    parts = os.listdir(fromdir)
    parts.sort()

    for part in parts:
        path = os.path.join(fromdir, part)
        infile = open(path, 'rb')

        while True:
            read = infile.read(readsize)
            if not read:
                break
            output.write(read)

        infile.close()

    output.close()


def command():

    if len(sys.argv) == 2 and sys.argv[1] == '--help':
        print('Use: ./join.py [from-dir-name to-file-name [read-size]]')
    else:

        if len(sys.argv) < 3:
            interactive = True
            fromdir = input('请输入分割文件所在的目录:')

            if 'splited_' in os.path.basename(fromdir):
                tofile = os.path.basename(fromdir).replace('splited_', '')
                tofile = input('请输入合并后的文件名(回车后默认{}):'.format(tofile)) or tofile
            else:
                tofile = input(
                    '请输入合并后的文件名(回车后默认{}):'.format(os.path.basename(fromdir))
                ) or os.path.basename(fromdir)

            readsize = input('请输入每次读取的字节大小(回车后默认1024):') or 1024
            readsize = int(readsize)

        else:
            interactive = False
            fromdir, tofile = sys.argv[1], sys.argv[2]
            readsize = 1024

            if len(sys.argv) > 3:
                readsize = int(sys.argv[3])

        absfrom, absto = map(os.path.abspath, [fromdir, tofile])
        print('将{}下的分割文件合并为{},每次读取{}字节'.format(absfrom, absto, readsize))

        try:
            join(fromdir, tofile, readsize=readsize)
        except Exception:
            print('合并失败')
            print(sys.exc_info()[0], sys.exc_info()[1])
        else:
            print('合并成功:{}'.format(absto))

        if interactive:
            input('按回车键退出……')


if __name__ == '__main__':
    command()

输出:join.py

$ ./my_PP4E/system/filetools/split.py ./my_PP4E/system/filetools/split.py splited_split.py 1
将/media/beacherhou/Git仓库/python-programming---markdown-notes/my_PP4E/system/filetools/split.py分割到/media/beacherhou/Git仓库/python-programming---markdown-notes/splited_split.py中,每个文件1.0kb
分隔成功:3个分割文件在/media/beacherhou/Git仓库/python-programming---markdown-notes/splited_split.py中
$ ./my_PP4E/system/filetools/join.py splited_split.py split.py 1
将/media/beacherhou/Git仓库/python-programming---markdown-notes/splited_split.py下的分割文件合并为/media/beacherhou/Git仓库/python-programming---markdown-notes/split.py,每次读取1字节
合并成功:/media/beacherhou/Git仓库/python-programming---markdown-notes/split.py
$ ls
第二部分_系统编程  jupyter  LICENSE  my_PP4E  PP4E  README.md  splited_split.py  split.py
$ ./my_PP4E/system/filetools/join.py
请输入分割文件所在的目录:splited_split.py
请输入合并后的文件名(回车后默认split.py):
请输入每次读取的字节大小(回车后默认1024):
将/media/beacherhou/Git仓库/python-programming---markdown-notes/splited_split.py下的分割文件合并为/media/beacherhou/Git仓库/python-programming---markdown-notes/split.py,每次读取1024字节
合并成功:/media/beacherhou/Git仓库/python-programming---markdown-notes/split.py
按回车键退出……
$ cat split.py 
#!/usr/bin/env python
"""
将文件分割成很多部分,join.py将它们合并回去;
这是标准的Unix split命令行工具的一个可移植版本,因为它用Python写成,所以在Windows下也能工作和方便的修改;
因为它包装成一个函数,所以它的逻辑业务也可以由其他命令程序导入并重复使用。
"""

import sys
import os


def split(fromfile, todir, chunksize=1024 * 1024):
    if not os.path.exists(todir):
        os.mkdir(todir)
    else:
        input('即将删除{}下的所有内容,按回车键继续……'.format(todir))
        for eachfile in os.listdir(todir):
            os.remove(os.path.join(todir, eachfile))
    partsnum = 0
    infile = open(fromfile, 'rb')

    while True:
        chunk = infile.read(chunksize)

        if not chunk:
            break

        partsnum += 1

        filename = os.path.join(todir, 'part{:0>10}'.format(partsnum))
        part = open(filename, 'wb')
        part.write(chunk)
        part.close()

    infile.close()
    assert partsnum <= 9999999999, "文件过大"
    return partsnum


def command():
    if len(sys.argv) == 2 and (sys.argv[1] == '--help' or sys.argv[1] == '-h'):
        print('Use: ./split.py [file-to-split target-dir [chunksize]]')
    else:
        chunksize = 1024 * 1024

        if len(sys.argv) < 3:
            interact = True
            fromfile = input('请输出要分割的文件:')
            todir = 'splited_' + os.path.basename(fromfile)
            todir = input(
                '请输入存储分割后的文件的目录(回车后默认{}):'.format(todir)
            ) or todir
            chunksize = input('请输入分割后文件kb大小(回车后默认1024):') or 1024
            chunksize = int(chunksize) * 1024
        else:
            interact = False
            fromfile, todir = sys.argv[1: 3]
            if len(sys.argv) == 4:
                chunksize = int(sys.argv[3]) * 1024

        absfrom, absto = map(os.path.abspath, [fromfile, todir])
        print('将{}分割到{}中,每个文件{}kb'.format(absfrom, absto, chunksize / 1024))

        try:
            partsnum = split(fromfile, todir, chunksize=chunksize)
        except Exception:
            print('分割失败')
            print(sys.exc_info()[0], sys.exc_info()[1])
        else:
            print('分隔成功:{}个分割文件在{}中'.format(partsnum, absto))
        if interact:
            input('按回车键退出……')


if __name__ == '__main__':
    command()

———————————————————————————————————————————

😃 学完博客后,是不是有所启发呢?如果对此还有疑问,欢迎在评论区留言哦。
如果还想了解更多的信息,欢迎大佬们关注我哦,也可以查看我的个人博客网站BeacherHou

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐