技术文章
2026-08-14
7 阅读
大文本文件拆分脚本:按行拆分并保留编码,支持GBK/UTF-16
使用示例
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
)