TextForever 文件合并与 TXT 段落合并:编码统一与断行阈值全解析
2026/9/15 16:12:08 网站建设 项目流程

简介:TextForever是一款面向TXT文本整理与电子书预处理场景的轻量工具,尤其适合需要合并小说章节、统一文本编码或清洗段落格式的阅读爱好者和文本编辑用户。程序内置丰富功能:支持网页转文本、文件合并、段落合并与分行,支持多种编码格式的相互转换,其中编码转换功能仅面向Windows 2000/XP环境;同时还具备文本替换、网页代码整理、文件切分、文本提取、正则表达式以及TCR批量压缩与解压能力,基本覆盖电子书预处理各环节。压缩包内共有两个文件,一个为可直接运行的exe主程序,另一个为配套的htm说明文档,整体体量约245KB,适合快速下载与本地使用。当前已有177人学习下载。通过实际使用,读者可以利用主程序配合说明文档,快捷完成文本文件的章节合并、段落重排、编码转换和内容提取,减少手工逐条整理的重复劳动,尤其适合对大量小说文本进行批量规范化的场景。

1. TextForever 文件合并和 TXT 段落合并到底在解决什么

TextForever(文本永存)处理文件合并和 TXT 段落合并,不是把一堆 txt 堆在一起那么简单。早年网文站章节页每行排 30 到 40 个字符就强制换行,这些「假换行」被复制进本地后,段落全被拆碎。直接复制粘贴或命令串文件,得到的是行行断裂、章节标题混进正文、编码交替乱码的文本。

TextForever 把文件合并、段落合并、编码转换放进同一条流程:先判断哪些换行是真的,再决定怎么拼接,最后按列表顺序输出。顺序、阈值、标点集合这些参数决定了成品质量,界面本身反而没什么可学的。

适合整理连载合订本的读者、做文本清洗的编辑、需要合并系统导出 txt 的运维与数据处理岗。不写脚本也能用,但理解判定逻辑能少走弯路。

2. TextForever 文件合并前的准备:列表顺序、编码统一与批量改名

文件合并在 TextForever 里是最后一步,前两步常被跳过:顺序和编码。列表里文件怎么排,输出就怎么排;编码不一致,合出来就是半本乱码。这两件事处理完,合并本身点一下就行。

2.1 文件列表顺序,决定合并后的章节目录顺序

TextForever 主界面是「文件列表 + 功能页签」的结构。把章节文件拖进列表后,合并结果严格按列表从上到下输出,不会自动做任何智能重排。常见做法是先把目录下的 txt 按名称排序,再全选拖入,最后眼睛扫一遍列表里第 1 章到最后一章的排列。

从资源管理器拖拽时,拖入顺序继承 Explorer 当前的排序。如果文件夹上次按「修改日期」排列,拖进去就是乱的;更隐蔽的是「第2章」排在「第10章」后面——纯字典序比较时,字符 '1' 小于 '9',所以第 10、11 章会被排到第 2 章前面。

对策是让文件名可自然排序:给章节号补零。数字部分改成三位数后,第 2 章永远排在 第 10 章前面,TextForever 的列表和资源管理器的排序结果一致,检查时不用来回找。用 PowerShell 批量改名,几十个文件一秒钟处理完:

# 将“第1章”改为“第001章”,保证字典序与自然序一致 Get-ChildItem -Path . -Filter '第*章*.txt' | ForEach-Object { if ($_.BaseName -match '第(\d+)章(.*)$') { $num = $Matches[1] $rest = $Matches[2] $newName = '第{0:D3}章{1}.txt' -f [int]$num, $rest Rename-Item -LiteralPath $_.FullName -NewName $newName } }

-match从文件名里提取「第」与「章」之间的数字和章名剩余部分;{0:D3}把 1、12、123 统一补成三位数,D3表示十进制最少三位。-LiteralPath避免文件名里的方括号被当成通配符。跑完再用Get-ChildItem | Select-Object Name确认一遍,书名号、空格、全角括号都不影响这条命令。

2.2 编码不统一时的判断与统一:GBK、UTF-8、BOM

txt 没有统一的编码标准。记事本默认「ANSI」在简体中文 Windows 上就是 GBK;从网站和阅读器拿到的文件很多是 UTF-8;个别老设备导出的是 UTF-16。TextForever 的「编码转换」功能可以批量处理,合并对话框里也有输出编码下拉框。判断一个文件是什么编码,先看文件头最可靠:

文件特征判断方法合并前处理
记事本另存、老网站下载中文两字节,开头无 BOM转 UTF-8 无 BOM
下载站常见UTF-8 无 BOM,中文三字节保留,输出编码选 UTF-8
带 BOM 的 UTF-8文件头 EF BB BF统一转无 BOM,避免拼接处出现不可见字符
UTF-16文件头 FF FE 或 FE FF先转 UTF-8 再进合并列表

拿不准时用下面这条 PowerShell 看每个文件的前几个字节。UTF-8 的 BOM 是 EF BB BF,UTF-16 是 FF FE 或 FE FF,GBK 没有固定文件头,只能靠排除法归类;这套规则已经能覆盖网文、导出文档和日志 txt 的绝大多数场景:

# 按文件头字节判断编码,GBK 无文件头标记,归为“疑似” Get-ChildItem *.txt | ForEach-Object { $b = [System.IO.File]::ReadAllBytes($_.FullName) if ($b.Length -ge 3 -and $b[0] -eq 0xEF -and $b[1] -eq 0xBB -and $b[2] -eq 0xBF) { $c = 'UTF-8 BOM' } elseif ($b.Length -ge 2 -and $b[0] -eq 0xFF -and $b[1] -eq 0xFE) { $c = 'UTF-16 LE' } elseif ($b.Length -ge 2 -and $b[0] -eq 0xFE -and $b[1] -eq 0xFF) { $c = 'UTF-16 BE' } else { $c = 'GBK/ANSI(疑似)' } '{0} {1}' -f $_.Name, $c }

这段脚本把每个文件的头两三个字节和 BOM 硬编码做比较,输出一行「文件名 + 判断结果」,几百个文件一眼扫完。经验法则是:从中文网站直接另存、从聊天软件传的文件基本是 GBK;从阅读器、在线转换站、命令行工具生成的多半是 UTF-8。转换时全部指向 UTF-8 无 BOM,合并输出也选 UTF-8,后续处理最省事。

提示:合并后出现「整章乱码、其他章正常」时,不要进正文手工改。回到原始文件看文件头,统一编码后重新合并,比重打快得多。

2.3 合并输出参数:文件间空行与输出编码

TextForever 的文件合并一般会让选择输出文件、输出编码,以及文件之间是否插入内容。我通常勾选「每文件间空一行」,否则上一章结尾和下一章开头会贴在一起;章节文件首行本身就是标题时,也可以不插空行,靠段落合并的空行规则处理,但后续改排版会更麻烦。

输出文件不要和被合并的源文件放在同一目录,更不要用「输出.txt」这类会被再次全选进去的名字。常见做法是建一个 merge_out 子目录,合并后把原始章节目录原样保留到确认无误再清理。顺序和编码这两件事做完,文件合并本身只需要十几秒。

3. TXT 段落合并的参数拆解:断行阈值、段尾标点与预览

段落合并不等于「删掉所有换行」。把全文合成一行只会让章节标题、对话引号全部粘死;真正要做的是把「因排版宽度被拆开的行」重新接回原来的段落,同时保住真段落边界。

3.1 先认出假换行:用行宽分布统计断行阈值

假换行来自阅读器和网页的流式排版:一行排满容器宽度就插入换行符。不同来源的断行宽度不一样,手机端常见 30 到 40 个字符,网页宽屏可能到 80 到 100。无论文本来自小说 URL 转 txt 的在线转换站,还是番茄小说这类客户端的导出内容,断行特征都一样藏在行宽里。段落合并前先统计行宽分布,阈值才有依据,而不是随手填个 40。

统计行宽最直接的办法是逐行打印字符数再做分布,Windows 上我一般用 PowerShell 的 Group-Object 完成同样的事,结果按行数降序排列,峰值就是断行宽度:

# 统计每种行长出现次数,Count 大的行宽即断行峰值 Get-Content -Path 第001章.txt | ForEach-Object { $_.Length } | Group-Object | Sort-Object Count -Descending | Select-Object -First 15 Count, Name

输出里 Count 是行数,Name 是该行长度的字符数。峰值集中在 30 到 45,说明这些文件按手机屏宽度断行,段落合并阈值设 45 到 55 比较稳妥;峰值在 80 以上,阈值要跟着提到 100。混合来源的文件,按最宽的峰值来设,或者先按来源分类再合并。在 Windows PowerShell 5.1 里 Get-Content 默认按 ANSI 解码,和 GBK 文本正好匹配;PowerShell 7 默认 UTF-8,遇到 GBK 文件统计出的行长会翻倍,所以规范做法是先统一编码再统计。

3.2 段落合并判定逻辑:空行、段尾标点与行宽阈值

段落合并的常见做法是逐行扫描,累加拼接,遇到三种信号之一就结束当前段落:空行;行尾出现句末标点;行宽达到阈值,说明这行本身已是一整段。行尾的逗号、分号、冒号不能作为段尾信号,否则列举句会被一节节切开。章节标题这类短行要单独保护,否则「第001章 云深不知处」会被并进下一段正文。

TextForever 的段落合并参数通常就这三项:断行阈值、段尾标点集合、是否在拼接处插入空格。有的版本把标题保护做成复选框,有的版本需要自己用正则预先把标题行前后补空行。我的习惯是不依赖选项,先保证标题行上下有空行,让空行信号替我做保护。

参数我常用的值什么时候改
断行阈值50 个字符统计峰值是网页宽屏就调到 90;手机端就 40
段尾标点集合。!?…」』”文本混入英文段落时补上 . ! ?
拼接处是否插空格不插中英混排且原文行尾带空格时才考虑保留

「拼接处不插空格」对中文最重要。英文排版依赖空格分词,中文不需要;勾选插入空格后,合并出来的正文每隔三四十个字就有一个多余空格,后期清洗反而更麻烦。这个参数在纯中文文本上永远选不插。

3.3 执行前预览:标题行、对话引号与诗歌

执行前必须预览,老版本没有预览区就复制一章出来试跑。第一看章节标题有没有被并走;第二看对话引号,中文对话常以「或“开头,行尾只出现半个右引号时,段尾标点集合里必须包含右引号,否则引号和正文会被拆到两个段落;第三看诗歌和剧本,五言诗每行五个字,按阈值全会被并成一个大段,预览里出现上千字的段落就说明并过头了。

针对诗歌可以用一个笨办法:先搜索以逗号结尾的短行,手动在这些行前后加空行。文本里以逗号结尾且整行很短的行,在散文里极罕见,在诗词里极常见;这一条规则能在不损失散文段落的前提下保住大部分诗行,比在参数里加排除规则更可控。

注意:别在段落合并前做「删除空行」操作。空行是段落边界的核心信号,删了它,合并器只能靠阈值和标点猜,误并率会明显上升。

4. 用 TextForever 完成 TXT 文件合并与段落合并:流程、检查与脚本兜底

4.1 完整处理流程:七步把章节 txt 合并成合订本

以最常见的网文合订本为例,完整流程是七步:建工作目录并拷入全部章节;统计行宽确定阈值;检查并统一编码;整理列表顺序;执行段落合并;执行文件合并;抽样检查输出。每一步都可以在 TextForever 里完成,只有统计和检查会用到命令行:

  1. 建目录,把章节按文件名顺序放好,原始文件留一份备份。
  2. 跑第 3.1 节的行宽统计命令,记录峰值,确定段落合并阈值。
  3. 用「编码转换」把所有文件转成 UTF-8 无 BOM;乱码文件单独看文件头。
  4. 全选拖入文件列表,按名称核对一遍,必要时零填充改名后重新添加。
  5. 进「段落合并」,填阈值、勾选标题保护、不插空格,先对单个章节执行并预览。
  6. 全选执行段落合并。
  7. 进「文件合并」,输出到 merge_out/合订本.txt,输出编码选 UTF-8,勾选文件间空一行。

第 5 步最容易省掉。直接对 800 个文件跑段落合并,参数错了要重新来八遍;先拿第一个和最后一个章节试跑,确认标题和引号都没被并坏,再全选执行。多数版本段落合并直接改写列表里的原文件,所以试跑前先复制两个样本文件到单独目录更安全。

4.2 合并后检查:段长分布脚本

合并完不要急着关工具。用一段 Python 统计输出文件的段落长度分布,能快速暴露「还有断行没并」和「段落被并过头」两类问题。把下面脚本存成 check_para.py,运行时直接传文件路径:

import re import sys from collections import Counter def paragraph_stats(path): text = open(path, encoding='utf-8').read() # 按空行切分段落 paras = [p for p in re.split(r'\n\s*\n', text) if p.strip()] # 按长度分桶,暴露误并/漏并 dist = Counter( '超长(>1000)' if len(p) > 1000 else '过短(<20)' if len(p) < 20 else '正常' for p in paras) return len(paras), dict(dist), max(len(p) for p in paras) if __name__ == '__main__': count, dist, max_len = paragraph_stats(sys.argv[1]) print('段数:', count, '最大段长:', max_len) print(dist)

re.split(r'\n\s*\n', text)用空行做段落边界,\s*匹配连续多个空行;Counter 把段落按长度分桶。正常小说合订本,「正常」占比应超过八成,最大段长一般不超过八百字。过短段占比高,说明阈值太小或段尾标点集合漏了右引号;超长段扎堆,则是标题行或诗歌被并了进去,回到第 5 步改保护规则重跑。

4.3 三个高频失败现象与检查点

现象可能原因检查点
某章整段乱码,其余正常该文件编码没统一看原始文件头,重跑编码转换
章节标题消失或粘在正文里标题保护没开,或标题前无空行试跑时检查「第X章」行
引号段落只合并了一半段尾标点集合少了右引号补上 」’ ” 后重跑

三个现象对应三个常被忽略的细节:编码检查只在合并前做一次,合并后再发现只能重来;标题保护依赖正则匹配,章节号是全角数字(如「第12章」)时匹配不上;引号集合要和文件里实际使用的引号写法一致,中文引号有「」、『』、“”三种,段落合并前统一成一种,比在参数里列全省事。

4.4 脚本兜底:复现段落合并判定逻辑

TextForever 适合交互式整理;要定时批量处理,或文件在服务器上生成,可以用下面的 Python 复现段落合并逻辑。它把前文的规则直接落成代码:短行且行尾无句末标点则拼接,空行和标题行保留为段落边界:

import re END_PUNCT = '。!?…」』”' TITLE_RE = re.compile(r'^第\s*[\d一二三四五六七八九十百千]+\s*[章节卷部回集].*') def reflow(text, threshold=50): out, buf = [], [] for raw in text.replace('\r\n', '\n').split('\n'): line = raw.strip() # 空行:段落边界,先落盘已有内容 if not line: if buf: out.append(''.join(buf)); buf = [] continue # 章节标题:独立成段,不参与拼接 if TITLE_RE.match(line) and len(line) < 30: if buf: out.append(''.join(buf)); buf = [] out.append(line) continue buf.append(line) # 段尾标点或行长达标,结束当前段 if line[-1] in END_PUNCT or len(line) >= threshold: out.append(''.join(buf)); buf = [] if buf: out.append(''.join(buf)) return '\n\n'.join(out)

threshold对应断行阈值;END_PUNCT对应段尾标点集合;TITLE_RE是标题保护正则,兼容「第12章」「第 12 章」「第一百二十章」「第1回」几种写法,len(line) < 30是为了避免把长句误判成标题。line.strip()会去掉行首行尾空白,缩进信息在这一步丢失,所以要求输入文本已经用空行区分段落——这也是前面强调「合并前不要删空行」的原因。输出用两个换行做段落分隔,正好匹配 4.2 的统计脚本。

5. 进阶技巧:跨文件段落合并的次序、二次清洗与收尾校验

5.1 段落合并和文件合并的次序选择

要不要把段落合并放在文件合并之前,取决于一个判断:上一章的结尾和下一章的开头是否可能属于同一个段落。先段落合并再文件合并,是我大多数时候的选择:每个章节内部先恢复段落,文件合并时用空行隔开章节,边界干净;先文件合并再段落合并,能续上跨文件的断段,但依赖标题保护规则兜底,适合 OCR 和 PDF 转出来、章节边界本身就混乱的文本。

5.2 合并后的正则二次清洗

段落合并解决断行,不解决脏字符。合并输出常见三个问题:行尾混入全角空格、连续空行过多、标题上方没有空行导致阅读器分章失败。用 Python 做清洗,逻辑比在 GUI 里逐条替换直观:

import re def polish(path): text = open(path, encoding='utf-8').read() text = text.replace('\r\n', '\n') # 删行尾的半角空格、制表符、全角空格 text = re.sub(r'[ \t\u3000]+\n', '\n', text) # 给章节标题前后补空行,便于阅读器生成目录 text = re.sub(r'(?m)^第[0-9零一二三四五六七八九十百千]+[章节卷部回集].*$', lambda m: '\n' + m.group(0) + '\n', text) # 空行归一,把补出来的 3 连空行压回 2 个 text = re.sub(r'\n{3,}', '\n\n', text) open(path, 'w', encoding='utf-8').write(text)

第一条删掉行尾空白;第二条用多行模式锚定行首,给章节标题前后各补一个换行;第三条把三个以上空行压成一个。顺序不能反:先补标题空行,最后做空行归一,否则先压缩出的单个空行又会被标题正则撑开。清洗放在段落合并之后,段落合并要依赖行尾状态判断断行,提前清空格等于破坏输入特征。

5.3 用三个数字做收尾校验

处理完只看三个数字:总行数、段落数、最大段长。总行数用(Get-Content 合订本.txt).Count拿,段落数和最大段长用 4.2 的脚本。行数与合并前各章节行数之和差在 5% 以内,说明没大规模吞行;段落数接近每章平均段数乘以章节数,说明边界正常;最大段长没超过 800,说明没有诗歌或剧本被并穿。这三个数字同时正常,这份 txt 的章节目录排版和段落结构就可以交给阅读器了。

合完先别删原始章节目录,改名为 raw_backup 留到阅读器里翻完一遍再清理。阅读器能正确生成章节目录、每章断页位置正确,这本合订本才算真正完成。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询