Perl 10:字符长度与输出字节要分别验收
解码后用 length 可以得到字符数,却不能据此推断写入文件的字节数。对于源码字面量 日志,字符数是 2,UTF-8 字节数是 6。报表或 JSON Lines 如果先编码一次,又经过另一层自动编码,文件内容就可能不等于金标;测试“屏幕上看起来正确”不足以排除这种错误。
Course 入口 examples/perl-language/bin/logtool 把 STDOUT 设为 :raw,在 report 命令里先构造 TSV 字符串,再用 Encode::encode('UTF-8', ..., FB_CROAK | LEAVE_SRC) 得到字节。course-semantics.pl unicode 的 decoded_chars=2 bytes=6 是最小机制断言;tools/replay.pl --case all 则走完整入口,记录 import、query、report 的 stdout SHA-256。两层证据分工不同:前者说明字符/字节边界,后者说明当前 CLI 输出字节与金标守恒。
图:输入解码、字符处理与输出编码
1 | |
另一个反例是重复解码。course-semantics.pl unicode 先把 UTF-8 字节解码成字符标量,再故意把该字符标量交给 decode('UTF-8', ..., FB_CROAK),输出 double_decode=error utf8_flag=1。这条断言防止把“已经是字符”的标量再次当作原始八位字节处理。Course 主线的 JSON Lines 同时保留 message 与 raw_message,并只对 message 做 NFC 规范化;这不是“所有字段统一改写”的承诺。
练习:一份金标只标注“输出 2”,能否验证 UTF-8 报表?不能;数字 2 可以是字符数,也可以是记录数。固定字节金标应注明编码、换行、输出通道和命令入口。复跑证据见 completion/evidence/semantics/*replay-all.* 与 completion/evidence/semantics/*course-semantics*;参考官方 Perl 5.38.2 pod/perluniintro.pod(Handling Unicode)、pod/perlunicode.pod(Byte and Character Semantics),以及 Encode 的 CHECK/LEAVE_SRC 语义。









