兩本整本書要先並成一份,才談得上下一站
古籍文本往下走,第一步往往不是演算法而是串接:一部書佔一個 TXT,切分和檢索要做兩遍。這次直接上整本——範本 txt-merge.html 現場 10126 字節、234 行,腳本段 6844 字節 169 行原樣進 node:vm 跑,源碼一行沒改,DOM 按 9 個 id 建樁;本輪純 Node、沒開瀏覽器。
兩部公版古籍:古文觀止那份 445453 字節、LF 2089 處、切出 2090 段、JS 串長 150341;浮生六記那份 110280 字節、LF 244、245 段、串長 36958。一次放進文本合併,下拉選單停在預設檔。
面板、落盤、逐本切段,三套尺各讀一個數
統計列給出 檔案數 2、總行數 2334、總字元數 187299;同一份產物落盤 555733 字節,按行數出來只有 2333。行數不是加出來的:兩書段數之和 2335,合併後少 1;兩書 LF 之和 2333,合併後多 1。九個檔位裡,面板行永遠比落盤行大 1——那一格走 result.split('\n').length,末尾換行之後的空段也佔一格。字節與字元兩層是純加,兩本各自之和與合併產物都差 0,倍數 2.9671。
圖 1:段數、LF、面板行、落盤行這四把尺都擠在 2333 到 2335 三格之內。
四個分隔檔位,逐檔加幾行、幾字、幾字節
四個 option 都沒有 selected,瀏覽器預設落第一項「無分隔」,getSeparator(L168–L175)因此回傳空字串。行賬只由分隔串含幾個換行決定:面板行 = ΣLF + (n−1)×LF(分隔串) + 1,勾選標記再疊 n;13 個檔位組合的預測與讀數逐字相等。
| 檔位 | 面板總行數 | 總字元數 | 落盤字節 |
|---|---|---|---|
| 無分隔 | 2334 | 187299 | 555733 |
| 換行 | 2335 | 187300 | 555734 |
| 空行 | 2336 | 187301 | 555735 |
| 自訂三橫槓 | 2334 | 187302 | 555736 |
| 空行加標記 | 2338 | 187343 | 555793 |
自訂框留空不是回退,那一支原樣取空字串,所以與無分隔逐字節同賬。串裡不含換行就不加行:三橫槓 +3 字 0 行、縫隙段成 12 碼元,四個等號 +4 字 0 行,帶換行才加行。
差的那一格不在尾換行
兩書末字節都是 0x0A、回車字節 0 處,縫隙段因此逐字等於浮生六記首行,9 碼元獨立成段。砍掉末字節造出 A2(445452 字節、LF 2088、2089 段)與 B2(110279 字節、LF 243、244 段)跑 2×2:無分隔四組 2334 / 2333 / 2333 / 2332,對兩書段之和的差全是 -1;換行檔差全 0;空行檔差全 +1。末字節改的是縫隙內容——缺尾換行的那本排前面時縫隙成 55 碼元,即前書末行 46 碼元焊上 9 碼元,配三橫槓成 58。
檔案名標記:每塊恆為 13 加名長
標記串 '===== ' + name + ' =====\n'(L186)自帶 1 個換行,每塊恆為 13 加名長;核取方塊沒有 checked,預設不勾。四種命名實測:
- 中文書名各 8 碼元:每塊 21 碼元,兩塊 +2 行 +42 字,落盤多 58 字節——其中 8 枚漢字各佔 3 字節
- 拼音名各 17 碼元:兩塊 60 碼元
- 8 碼元配 34 碼元:68 碼元
- 帶目錄前綴各 20 碼元:66 碼元
行數增量恆為 2,字節增量卻各檔不同。
批次、重複投遞,以及它其實不即時
單書四檔同賬——單元素陣列 join 根本不插分隔串,2090 行 / 150341 字 / 445453 字節。六部(兩部各三遍,ΣLF 6999)無分隔 7000 / 561897 / 1667199,空行加標記 7016 / 562033 / 1667383;無分隔檔「面板減各檔案之和」恆為 -(n−1)。同一檔案再拖一次照樣入列,push 不判重;清單每批只重新整理 1 次,連點 3 次合併只是覆寫統計列 3 次。
改下拉、填自訂框、勾核取方塊之後結果區不動,兩控件的監聽器各 0 個,得再點一次合併才跳到 2338 行 / 187343 字;合併完補一個檔案,佇列已 3 項,面板仍寫 檔案數 2。
編碼與幾條失敗路徑
兩書首 3 字節都是 e3 80 90,即「【」的編碼,無字節順序標記,嚴格解一次通過、寬鬆解下替代字元各 0,這兩類賬在真書上無從發生。空清單點合併只彈「請先新增檔案」;0 字節檔案單獨合併給出 檔案數 1 / 總行數 0 / 總字元數 0 這組自相矛盾的讀數;一成一敗的混合批清單只 1 行,提示卻寫已新增 2 個。腳本段裡字節門檻、1024、max=、截斷切片全 0 處命中,1667199 字節的產物整串賦給結果框。
書本身數得出來的結構
古文觀止獨立成行的方括號標記 238 行(左右兩枚碼位各 238 次互證)=卷頭 12 + 書首 4 + 篇題 222;卷頭落在行序 44、248、438、590、713、806、904、1020、1136、1292、1510、1832,按這 12 行切區間逐卷數篇題:
圖 2:十二卷篇題數逐卷排開,三卷與九卷兩根 22 最高。
浮生六記的標記只有 4 行,落在行 1、54、91、148,各 9 碼元,是文本裡四卷的分界。同族兩頁各有一把尺:讀取那頁的字元欄與這裡的字元格同屬 JS 串長口徑。
對照清單文案,13 條判定裡 1 條站反
config/tools.php 第 1608 行起逐條判:[一致] 7、[部分一致] 5、[衝突] 1。部分一致的三條都跟賬有關——標題只舉 TXT,accept 卻放了 11 項;分隔符那句漏掉預設檔「無分隔」,自訂留空又不回退;「批次」只到前端串接這一層。站反的那條正是「即時預覽」。瀏覽器解碼本體的字面、磁碟編碼下檔案名的實際長度、187299 碼元寫進結果框的耗時與結果框可視高度,一律標未實測。
常見問題
Q:面板總行數為什麼總比落盤行數多 1?
那一格走 split 換行取段數,末尾換行之後的空段也算一格。
Q:分隔符選了自訂卻沒填,會退回無分隔嗎?
結果一樣但不是退回:那一支原樣取空字串、沒有兜底,產物與無分隔逐字節相同,555733 字節、2334 行、187299 字三數全等。
Q:改檔位或勾上標記,結果區會跟著變嗎?
不會,控件上沒有監聽器,改完得再點一次合併才從 2334 行跳到 2338 行、187343 字。