120 lines
4.4 KiB
Python
120 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""sendaiandsplit.py - TransPyV/includes 源码合并/分割工具
|
||
|
||
用法:
|
||
python sendaiandsplit.py 0 # 合并 TransPyV/App 下所有 .vp → ./TPV.vp
|
||
python sendaiandsplit.py 1 # 分割 ./TPV.vp → ./TPV0.vp, ./TPV1.vp, ...(每块 199KB)
|
||
python sendaiandsplit.py includes 0 # 合并 ./includes 下所有 .vp/.vp.txt → ./includes.vp
|
||
python sendaiandsplit.py includes 1 # 分割 ./includes.vp → ./includes0.vp.txt, ./includes1.vp.txt, ...(每块 199KB)
|
||
"""
|
||
import os
|
||
import sys
|
||
|
||
# 默认模式(TransPyV/App)配置
|
||
APP_DIR = os.path.join("TransPyV", "App")
|
||
APP_OUTPUT = "TPV.vp"
|
||
APP_SPLIT_PREFIX = "TPV"
|
||
|
||
# includes 模式配置(用户已将 includes 下文件后缀改为 .vp.txt)
|
||
INCLUDES_DIR = "includes"
|
||
INCLUDES_OUTPUT = "includes.vp"
|
||
INCLUDES_SPLIT_PREFIX = "includes"
|
||
|
||
# 分割块大小(199KB)
|
||
CHUNK_SIZE = 199 * 1024
|
||
|
||
|
||
def merge(src_dir: str, out_file: str, exts) -> int:
|
||
"""递归扫描 src_dir 下后缀匹配 exts(单个 str 或 tuple)的文件,按排序合并为 out_file"""
|
||
if not os.path.isdir(src_dir):
|
||
print(f"错误: 目录 {src_dir} 不存在", file=sys.stderr)
|
||
return 1
|
||
if isinstance(exts, str):
|
||
exts = (exts,)
|
||
|
||
matched = []
|
||
for root, _dirs, files in os.walk(src_dir):
|
||
for f in files:
|
||
if any(f.endswith(e) for e in exts):
|
||
matched.append(os.path.join(root, f))
|
||
matched.sort() # 稳定顺序,保证合并结果可复现
|
||
|
||
total = 0
|
||
try:
|
||
with open(out_file, "w", encoding="utf-8") as out:
|
||
for path in matched:
|
||
with open(path, "r", encoding="utf-8") as fh:
|
||
content = fh.read()
|
||
out.write(content)
|
||
if not content.endswith("\n"):
|
||
out.write("\n")
|
||
total += len(content)
|
||
except OSError as exc:
|
||
print(f"错误: 写入 {out_file} 失败: {exc}", file=sys.stderr)
|
||
return 1
|
||
|
||
print(f"合并完成: {len(matched)} 个文件 → {out_file} ({total} 字节)")
|
||
return 0
|
||
|
||
|
||
def split(in_file: str, out_prefix: str, out_ext: str) -> int:
|
||
"""将 in_file 按 199KB 分块,输出 {out_prefix}{number}.{out_ext}"""
|
||
if not os.path.exists(in_file):
|
||
print(f"错误: {in_file} 不存在,请先运行对应的合并命令", file=sys.stderr)
|
||
return 1
|
||
|
||
try:
|
||
with open(in_file, "r", encoding="utf-8") as fh:
|
||
data = fh.read()
|
||
except OSError as exc:
|
||
print(f"错误: 读取 {in_file} 失败: {exc}", file=sys.stderr)
|
||
return 1
|
||
|
||
n = 0
|
||
for i in range(0, len(data), CHUNK_SIZE):
|
||
chunk = data[i:i + CHUNK_SIZE]
|
||
name = f"{out_prefix}{n}.{out_ext}"
|
||
try:
|
||
with open(name, "w", encoding="utf-8") as out:
|
||
out.write(chunk)
|
||
except OSError as exc:
|
||
print(f"错误: 写入 {name} 失败: {exc}", file=sys.stderr)
|
||
return 1
|
||
print(f"{name}: {len(chunk)} 字节")
|
||
n += 1
|
||
|
||
print(f"分割完成: {n} 个文件(每块上限 199KB)")
|
||
return 0
|
||
|
||
|
||
def print_usage() -> None:
|
||
print("用法: python sendaiandsplit.py <0|1> [或] python sendaiandsplit.py includes <0|1>", file=sys.stderr)
|
||
print(" 0 = 合并 TransPyV/App 下所有 .vp → ./TPV.vp", file=sys.stderr)
|
||
print(" 1 = 分割 ./TPV.vp → ./TPV0.vp, ./TPV1.vp, ...(每块 199KB)", file=sys.stderr)
|
||
print(" includes 0 = 合并 ./includes 下所有 .vp/.vp.txt → ./includes.vp", file=sys.stderr)
|
||
print(" includes 1 = 分割 ./includes.vp → ./includes0.vp.txt, ./includes1.vp.txt, ...(每块 199KB)", file=sys.stderr)
|
||
|
||
|
||
def main() -> int:
|
||
args = sys.argv[1:]
|
||
|
||
# 默认模式: sendaiandsplit.py 0|1
|
||
if len(args) == 1 and args[0] in ("0", "1"):
|
||
if args[0] == "0":
|
||
return merge(APP_DIR, APP_OUTPUT, ".vp")
|
||
return split(APP_OUTPUT, APP_SPLIT_PREFIX, "vp")
|
||
|
||
# includes 模式: sendaiandsplit.py includes 0|1
|
||
if len(args) == 2 and args[0] == "includes" and args[1] in ("0", "1"):
|
||
if args[1] == "0":
|
||
# 同时匹配 .vp 与 .vp.txt(用户计划将 includes 后缀改为 .vp.txt)
|
||
return merge(INCLUDES_DIR, INCLUDES_OUTPUT, (".vp", ".vp.txt"))
|
||
return split(INCLUDES_OUTPUT, INCLUDES_SPLIT_PREFIX, "vp.txt")
|
||
|
||
print_usage()
|
||
return 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|