Files

笔画表

随包笔画码表的源数据:字\t序列,序列按大陆笔顺,1 横 / 2 竖 / 3 撇 / 5 折 / n 点与捺 (CNS 的 4 同时涵盖点与捺,按设计文档「点捺合并为 n」写成 n;提在 CNS 里多数已记 1,氵的第三笔记 4,由覆盖表改回 1)。 单字取码「前 4 笔 + 末笔」、词组每字首笔,见 docs/design/aux-code.md 的「原生表:只带笔画」。

数据来源

用途 来源 许可 是否入库
字形来源(笔顺序列) CNS11643 中文標準交換碼全字庫「筆順資料」CNS_strokes_sequence.txt 政府資料開放授權條款第 1 版 或 OFL-1.1(二选一,可再分发含商用,需署名) 原始 zip 不入库(data/cns/,gitignore),只留生成产物
CNS→Unicode 映射 同一数据集的 MapingTables.zip(CNS2UNICODE_Unicode*.txt 4 个平面) 同上 不入库(data/cns/)
自洽过滤 同一数据集的 CNS_stroke.txt(筆畫數) 同上 不入库(data/cns/)
笔画数对照(开发期) Make Me a Hanzi / hanzi-writer-data 每字 medians 条数(PRC 字形) Arphic Public License,与仓库 GPL-3.0 不兼容;不进仓库、不随包,只作开发期对照 data/mmh/prc-counts-l1.tsv(mmh-reference 生成)
首笔对照(开发期) 同上,首笔 medians 的几何方向分类 同上 data/mmh/prc-first-strokes-l1.tsv(mmh-reference 生成)
首笔修正的规范依据 《通用规范汉字笔顺规范》(GF 0023—2020) 国家标准,只引笔顺事实、不复制文本 prc-rules.tsv 的修正行(来源注明该标准)

数据集页 https://data.gov.tw/dataset/5961,下载 https://www.cns11643.gov.tw/opendata/Properties.zip 与 https://www.cns11643.gov.tw/opendata/MapingTables.zip(解到 data/cns/);对照源 hanzi-writer-data-2.0.1.tgz(npm registry)解到 data/mmh/。 对照表再生成:cargo run -p qingjian-dict-convert -- mmh-reference(读 data/mmh/package/ 与字表,写上面两张对照表;data/ 已 gitignore,表不进仓库)。选型与许可依据见 docs/design/aux-code.md「原生表:只带笔画」与 wayfinder 的 t07(数据源查证)/ t09(归一化决议)两张票:CNS 作字形来源 + 大陆序覆盖表,MMH 只在开发期做对照。

文件

文件 内容
prc-rules.tsv 大陆序覆盖表:rule(部件重写)/ skip(例外字)/ char(整字补录)三类行,格式见文件头
data/mmh/prc-counts-l1.tsv 一级字大陆笔画数对照表(开发期对照用;mmh-reference 生成,不进仓库)
data/mmh/prc-first-strokes-l1.tsv 一级字大陆首笔几何对照表(同上;类别是几何近似,不是规范口径)
residual-whitelist.tsv 笔画数残留差异白名单:抽样里已知且接受的差异,白名单之外一处不符即验收失败
residual-first-strokes.tsv 首笔残留差异白名单:首笔对照里已知且接受的差异(规范裁定后保留的 CNS 结构性差异与对照源分笔假阳性)

生成与验收

# 生成(缺省写 data/generated/codes/stroke.tsv)
cargo run --release -p qingjian-dict-convert -- stroke --cns-count data/cns/CNS_stroke.txt --verify

--verify 两路对照(对照表由 mmh-reference 生成,找不到哪张就跳过哪张并提示):笔画数按「一级字表每 12 字取 1」(291 字)抽样比对;首笔按一级字表 3,500 字全量比对几何类别。几何类别分不清近竖的撇与点,但两岸笔顺的差异也落在这几类里,所以不按类别放行:不符的字逐字裁定后进首笔白名单。白名单之外一处不符即退出码非 0。对照源把撇也归成竖的字(册、删)对照不出来,靠人工抽查。

随包时再算成码表(缺省读 data/generated/codes/stroke.tsv 与 data/generated/dict.qj,写 data/generated/codes/stroke.qj):

cargo run --release -p qingjian-dict-convert -- pack codes

按设计文档的取码规则算码(单字「前 4 笔 + 末笔」、词组每字首笔,缺字的词跳过并计入统计);元数据缺省写明 名称「笔画」、许可 OFL-1.1、署名「CNS11643 全字庫筆順資料(數位發展部)」与数据集页来源, 可用 --name / --license / --attribution / --source / --data-version 覆盖(数据版本缺省取笔画表日期)。 产物随包只带生成结果,原始 zip 与对照源都不入库。

验收记录(2026-09-21,首笔第二轮)

已读大陆序覆盖表 rules=12 overrides=79
已生成笔画表 entries=7991 dropped_no_sequence=111 dropped_inconsistent=3
笔画数对照完成 sampled=291 reference_entries=3500 whitelisted=7 unmatched=0
首笔对照完成 compared=3092 absent=0 whitelisted=408 unmatched=0
  • 去掉首笔对照的三类近似放行后重新裁定:师、归(CNS 记点,应为竖)、非字头 / 非字旁(记撇,应为竖)、册 / 删(记竖,应为撇)、所(被「戶→户」规则误伤)改对;其余 343 字本表首笔是对的,进白名单。
  • 顺带按规范改了两处非首笔的笔顺:忄(点、点、竖)与 必(点、卧钩、点、撇、点)。
  • 一级字之外没有对照数据,只靠部件规则覆盖。

验收记录(2026-09-20,首笔修正后)

已读大陆序覆盖表 rules=10 overrides=66
已生成笔画表 out=data/generated/codes/stroke.tsv entries=7991 dropped_no_sequence=111
             dropped_inconsistent=3 average_strokes=10.92 size_kb=127
笔画数对照完成 sampled=291 reference_entries=3500 whitelisted=7 unmatched=0
首笔对照完成 compared=3435 absent=0 whitelisted=65 unmatched=0
  • 首笔:一级字 3,500 全对(GF 0023—2020);诞(一级字)原被 CNS 自洽过滤丢字,整字覆盖补录后重新入表(7,991 字)。
  • 笔画数:抽样(每 12 字取 1)白名单之外 0 条;全量对账 107 → 102,残留是 CNS 与大陆规范的结构性差异(评审已认可留待以后补)。阝 第二笔随规范改为竖后,其家族计数不变。
  • 端到端:pack codes 产 stroke.qj(91,773 词有码,诞 的词恢复 17 条),CLI --aux-table 可查。

验收记录(2026-09-15)

已读大陆序覆盖表 rules=8 overrides=1
已读 CNS→Unicode 对照表 entries=104680
已读筆順資料 entries=94919
已读筆畫數 entries=97361
已读字表白名单 chars=8105
已生成笔画表 out=data/generated/codes/stroke.tsv entries=7990 dropped_no_sequence=111
             dropped_inconsistent=4 average_strokes=10.92 size_kb=127 elapsed_ms=579
抽样对照完成 sampled=291 reference_entries=3500 whitelisted=7 unmatched=0
  • 抽样对照:291 字里 7 字不符,全部在白名单内,白名单之外 0 条(cargo test -p qingjian-dict-convert 的 stroke::tests 另外覆盖规则解析、锚点语义与对照/抽样逻辑)。
  • 产物:7,990 行 / 127,283 字节(平均 10.9 画)。设计文档估的 40–80 KB 偏小:那是按「前 4 笔 + 末笔」的 5 码估的, 本表是全笔顺序列(字\t[1-5n]+)。
  • 覆盖面:通用规范字表 8,105 字里 7,990 字有码。CNS 对照表里没有的 112 字里,闹 由 char 行人工补录, 其余 111 字绝大多数是三级字表里的扩展 B 区字(𬉼 这类),另有 鿍 / 鿎 / 鿏(U+9FCD–9FCF); 另有 4 字(诞 铼 煺 藓)笔顺序列与 CNS 筆畫數差超过 1,被自洽过滤丢掉。
  • 已知范围(诊断,不入白名单口径):全量 6,861 个有对照的字里 241 字(3.5%)笔画数与大陆规范不符, 是 CNS 台湾标准与大陆规范在整字形 / 部件层面的结构性差异(例:瓦 5/4、卸 8/9、修 10/9、粤 13/12)。 设计文档「差异集中在艹 / 辶 / 阝」只对了一部分:覆盖表把不符从 926 处压到 241 处(修掉 685 处成片差异), 剩下的(及 / 巨 / 之 / 与 / 母 / 书 / 我 的字形与笔顺归类差异)不能由模式替换从 CNS 序列推出, 要逐字人工核;抽样白名单只登记落在抽样里的 7 个(--stride 越小抽样越密,白名单要同步增补)。
  • 已知范围之二:首笔不保证对(2026-09-16 补测,诊断口径)。上一节的抽样只比笔画数,比不出「笔数对、 顺序不同」的偏差。用开发期对照源(data/mmh/,hanzi-writer-data 的 medians)对全表首笔方向做了一次粗筛: 6,862 个可比字里 58 处(0.8%)方向与我们的首笔类型对不上,其中一部分是提 / 竖提 / 折这类「末端转向」被误判, 但 丰 / 耒 / 皮 一族的首笔确实可疑(丰 我们的序列 311:首笔记成撇,大陆规范是横),而首笔错了, 含这个字的每个词的码都跟着错。示例:发 535nn(首笔记成折,对照源的几何方向接近横)。 复现:node .scratch/first-stroke-audit.js(仓库外工具,脚本未入库);修法是把这类成片的字形差异补进 prc-rules.tsv(或加一张「首笔覆盖表」),再重跑 stroke + pack codes。

随包时的许可合规

  • 数据目录与「关于」页署名:資料來源「CNS11643 中文標準交換碼全字庫」(數位發展部),并声明本表为派生 (筆順資料表格 → 笔画码表)与修改内容(大陆序覆盖表);
  • 随包数据目录放 LICENSE-CNS11643.txt(本目录,OFL-1.1 全文,与码表元数据的许可一致;数据集允许与政府資料開放授權條款第 1 版二选一),Windows 与码表一起装在 data\generated\codes\。

来源:wayfinder 票 t17(stroke 工具与笔画表生成)与 spec 卷 I 第 8 章的 stroke 契约(在仓库外的 .wayfinder 工作区)。