技术文章

大文本文件拆分脚本:按行拆分并保留编码,支持GBK/UTF-16
技术文章 2026-08-14 7 阅读

大文本文件拆分脚本:按行拆分并保留编码,支持GBK/UTF-16

xiaoniba 小泥巴 2026-08-14

使用示例

1、默认:不指定--out‑enc,输出和源编码一模一样(不转码)

bash

python split_txt.py -i big.txt -n 200000 -p wubi_part

2、强制源文件是 gbk,输出也保持 gbk

bash

python split_txt.py -i big.txt -n 200000 -e gbk

3、源是 gbk,强制转输出为 utf‑8(需要转码的时候才加这个参数)

bash

python split_txt.py -i big.txt -n 200000 -e gbk --out-enc utf-8

4、源为 utf‑16‑le,输出也保留 utf‑16‑le

bash

python split_txt.py -i big.txt -n 200000 -e utf-16-le

关键行为

不写--out‑enc:分片输出编码 = 源文件编码,不会自动转 UTF‑8;

只有传入--out‑enc xxx才会执行编码转换;

UTF‑16‑le/be BOM:Python 在写文件时会自动输出对应 BOM 头,和 Windows 记事本行为一致;

依赖依旧:pip install chardet。

小提示:处理五笔词库,如果后续要给深蓝词库转换 / WubiLex,建议显式加上 --out‑enc utf‑8 转成 utf‑8 无 BOM。


import argparse
import chardet

def detect_file_encoding(file_path: str) -> str:
    with open(file_path, "rb") as f:
        raw_data = f.read(1024 * 1024)

    if raw_data.startswith(b'\xff\xfe'):
        return "utf-16-le"
    if raw_data.startswith(b'\xfe\xff'):
        return "utf-16-be"

    res = chardet.detect(raw_data)
    enc = res["encoding"]
    conf = res["confidence"]
    print(f"???? 探测源文件编码: {enc} (置信度 {conf:.2f})")
    return enc


def write_file_with_bom(filepath: str, bom: bytes, out_encoding: str):
    # 先写BOM
    if bom:
        with open(filepath, "wb") as fb:
            fb.write(bom)
    # 返回文本模式句柄,追加写入
    return open(filepath, "a", encoding=out_encoding)


def get_bom_bytes(enc: str):
    if enc.lower() == "utf-16-le":
        return b"\xff\xfe"
    elif enc.lower() == "utf-16-be":
        return b"\xfe\xff"
    return b""


def split_large_txt(
    input_path: str,
    lines_per_chunk: int,
    prefix: str = "split",
    src_encoding: str = None,
    out_encoding: str = None
):
    if src_encoding is None:
        src_encoding = detect_file_encoding(input_path)

    if out_encoding is None:
        out_encoding = src_encoding
    print(f"ℹ️ 源编码:{src_encoding} | 输出分片编码:{out_encoding}")

    chunk_num = 1
    out_path = f"{prefix}_{chunk_num}.txt"
    bom = get_bom_bytes(out_encoding)
    out_fp = write_file_with_bom(out_path, bom, out_encoding)

    line_cnt = 0

    with open(input_path, "r", encoding=src_encoding) as in_fp:
        for line in in_fp:
            out_fp.write(line)
            line_cnt += 1

            if line_cnt >= lines_per_chunk:
                out_fp.close()
                print(f"✅ 已输出: {out_path}")
                chunk_num += 1
                out_path = f"{prefix}_{chunk_num}.txt"
                bom = get_bom_bytes(out_encoding)
                out_fp = write_file_with_bom(out_path, bom, out_encoding)
                line_cnt = 0

    out_fp.close()
    print(f"✅ 已输出: {out_path}")
    print("???? 文件拆分完成")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="大TXT按行拆分|修复UTF‑16每个分片独立BOM头"
    )
    parser.add_argument("-i", "--input", required=True, help="输入文件路径")
    parser.add_argument("-n", "--lines", type=int, required=True, help="每个分片最大行数")
    parser.add_argument("-p", "--prefix", default="split", help="输出文件前缀")
    parser.add_argument("-e", "--encoding", default=None,
                        help="手动指定源文件编码:utf-8,gbk,utf-16-le,utf-16‑be;不填自动探测")
    parser.add_argument("--out-enc", default=None,
                        help="【可选】指定输出分片编码,不设置则和源文件编码保持一致")

    args = parser.parse_args()
    split_large_txt(
        input_path=args.input,
        lines_per_chunk=args.lines,
        prefix=args.prefix,
        src_encoding=args.encoding,
        out_encoding=args.out_enc
    )


相关标签:

发表评论:

评论记录:

未查询到任何数据!
QQ咨询
回电话
回拨通话

我们稍后回拨您的电话

座机请加区号

微信联系
微信扫一扫
微信二维码

扫码加微信