有一份许久未打开的 Visual Studio 2017 工程,代码里有中文注释,因为是中文 Windows 环境,所以默认情况下文件编码是 GB2312 家族。 期间因为特殊原因将整个系统语言切换到了日语,现在又切回来了,Visual Studio 好像没有缓过劲,还在尝试用 Shift-JIS 加载文件,出现了标题所示的报错。
编码问题,只要不保存,就留得青山在。但是放弃脏文件再用 GB2312 编码打开后,虽然大部分中文注释恢复如初,但是个别句子末尾出现了乱码,同时 VS 提示 CRLF 和 LF 混用。
用 xxd 打印文本的十六进制表示后逐一比对,终于借助一些能够明确确定原文的句子,发现了字节上的错误:有乱码的文本里,一定有 81 45 这个字节串,且这个字节串总是在两个双字节的中间位置覆盖旧数据,导致解码过程出现错乱,只能看到 LF (0a) 才能恢复。
举例来说,原本注释里有“指针<换行>”这样的序列,GB2312 下的编码应该是: b6 d4 cf f3 0d 0a 但是现在乱码的文本是: b6 d4 cf 81 45 0a
大量的 <CR> <LF> 被破坏成 E <LF>,也难怪 VS 会提示 CRLF 和 LF 混用。
其他用 Shift-JIS 强行打开的 GB2312 代码文本不保存关闭后并没有出现 81 45 的字节序列,经过测试只有将强行打开的文件进行保存后才会有这种问题,看来我上面所使用的代码文件在反复开闭换编码的时候不小心保存了。
真正的问题是,VS 明明说是用 Unicode 替换字符替换,那应该是 \uFFFD,一个黑底菱形问号,81 45 感觉并不能在某个编码下找到对应的存在,Unicode 里 0081 是控制字符,而且有 00. 45 本身是 E,不可能在多字节编码里以其他含义出现,所以这替换行为实在是让人困惑。