You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Python按字节分割大文件的代码以保留行完整性?

可以实现,修改方案如下

核心思路

不再严格按固定字节数分割,而是在接近设定的分割大小时,继续读取直到找到行尾换行符,确保每个子文件的最后一行完整;同时处理文件末尾的边界情况,以及单行超过分割大小的极端场景。

修改后的完整代码

import os
import sys

def splitfile(spath, sfilename, splitsize, dpath):
    full_input_path = os.path.join(spath, sfilename)
    if not os.path.isfile(full_input_path):
        print(f"文件不存在: {full_input_path}")
        return

    # 自动创建输出目录(如果不存在)
    os.makedirs(dpath, exist_ok=True)

    # 分离文件名和后缀,避免多后缀文件名出错
    base_name, ext = os.path.splitext(sfilename)
    counter = 1

    with open(full_input_path, "rb") as fr:
        while True:
            buffer = b""
            bytes_written = 0

            # 按4KB块读取,兼顾效率和换行查找精度
            while bytes_written < splitsize:
                chunk = fr.read(4096)
                if not chunk:
                    break  # 文件读取完毕

                # 检查添加当前块是否会超出分割大小
                if bytes_written + len(chunk) > splitsize:
                    # 从当前块中找最后一个换行符的位置
                    newline_pos = chunk.rfind(b"\n")
                    if newline_pos != -1:
                        # 读取到换行符为止,剩余内容放回文件指针
                        buffer += chunk[:newline_pos+1]
                        bytes_written += newline_pos + 1
                        fr.seek(fr.tell() - (len(chunk) - newline_pos - 1))
                    else:
                        # 单行超过分割大小,直接保留整行
                        buffer += chunk
                        bytes_written += len(chunk)
                else:
                    buffer += chunk
                    bytes_written += len(chunk)

            if not buffer:
                break  # 无数据可写,退出循环

            # 生成带三位数字序号的子文件名
            output_filename = f"{base_name}_{counter:03d}{ext}"
            full_output_path = os.path.join(dpath, output_filename)

            # 写入子文件
            with open(full_output_path, "wb") as fw:
                fw.write(buffer)

            print(f"已生成子文件: {full_output_path}")
            counter += 1

if __name__ == "__main__":
    if len(sys.argv) < 5:
        print("使用方法: filesplit.py <输入文件路径> <输入文件名> <分割大小(KB)> <输出目录>")
        print("示例: filesplit.py ./ data.txt 102400 ./split_files")
        sys.exit(1)
    
    try:
        spath = sys.argv[1]
        sfilename = sys.argv[2]
        splitsize_kb = int(sys.argv[3])
        dpath = sys.argv[4]
        # 标准KB转字节(1KB=1024字节)
        splitsize = splitsize_kb * 1024
        splitfile(spath, sfilename, splitsize, dpath)
    except ValueError:
        print("分割大小必须是整数")
        sys.exit(1)

关键修改说明

  • 文件名处理优化:用os.path.splitext替代split("."),避免文件名含多个点时出错;用{counter:03d}生成三位数字序号,符合需求中的filename_001.txt格式。
  • 读取逻辑重构:
    • 采用4KB块读取,兼顾效率和换行查找的精度
    • 当即将超出分割大小时,查找当前块内的最后一个换行符,只读取到换行符位置,剩余内容放回文件指针留给下一个子文件
    • 处理单行超过分割大小的极端情况,确保整行完整保留
  • 参数修正:
    • 修复原代码命令行参数顺序错误的问题,明确参数含义
    • 用标准的1024将KB转换为字节(原代码用1000不符合单位定义)
    • 增加参数错误提示和异常捕获
  • 冗余代码移除:删除不必要的getfilesize函数,直接循环读取直到文件结束,逻辑更灵活
  • 输出目录处理:自动创建输出目录,避免因目录不存在导致报错

内容的提问来源于stack exchange,提问作者rob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:07:15