【发布时间】:2018-02-10 21:16:09
【问题描述】:
我在文件 utf8.txt 中有一些 UTF-8 文本。该文件包含一些超出 ASCII 范围的字符。我尝试了以下代码:
var fname = "utf8.txt";
var enc = Encoding.GetEncoding("ISO-8859-1", EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
var s = System.IO.File.ReadAllText(fname, enc);
预期的行为是代码应该引发异常,因为它不是有效的 ISO-8859-1 文本。相反,其行为是将 UTF-8 文本正确解码为正确的字符(在调试器中看起来是正确的)。
这是.Net 中的错误吗?
编辑:
我最初测试的文件是带有 BOM 的 UTF-8。如果我删除 BOM,行为会发生变化。它仍然不会抛出异常,但是它会产生一个不正确的 Unicode 字符串(该字符串在调试器中 not 看起来是正确的)。
编辑:
要生成我的测试文件,请运行以下代码:
var fname = "utf8.txt";
var utf8_bom_e_circumflex_bytes = new byte[] {0xEF, 0xBB, 0xBF, 0xC3, 0xAA};
System.IO.File.WriteAllBytes(fname, utf8_bom_e_circumflex_bytes);
编辑:
我认为我对正在发生的事情有一个坚定的把握(尽管我不同意 .Net 的部分行为)。
如果文件以 UTF-8 BOM 开头,并且数据是有效的 UTF-8,那么
ReadAllText将完全忽略您传入的编码并(正确)将文件解码为 UTF-8。 (我没有测试如果 BOM 是谎言并且文件不是真正的 UTF-8 会发生什么)我不同意这种行为。我认为 .Net 应该要么抛出异常,要么使用我给它的编码。如果文件没有 BOM,.Net 没有简单(并且 100% 可靠)的方法来确定文本不是真正的 ISO-8859-1,因为大多数(全部?)UTF-8 文本是也是有效的 ISO-8859-1,虽然是胡言乱语。所以它只是按照你的指示,用你给它的编码解码文件。 (我同意这种行为)
【问题讨论】:
-
您能否提供文件中您认为有问题的文本示例?
-
我想到了,但最好的方法是什么?我真的很想发布一个二进制文件。
-
可能只是您期望失败的几个字符编码,我们可以根据它重新创建文本吗?或者,也许我可以出去找到一些晦涩的 utf8 文本并使用它。我认为它不是特定字符,只是您担心的任何无效 ISO-8859-1 字符
-
ISO-8859-1 是 8 位编码,所以我相信 0x00 到 0xFF 的字符是允许的。
-
"因为大多数(全部?)UTF-8 文本也是有效的 ISO-8859-1" - 这仅适用于 ASCII 字节 0x20-0x7E,它们是相同的在 UTF-8 和 ISO-8859-1 中。一旦超出该范围,UTF-8 就不是有效的 ISO-8859-1。字节 0x00-0x1F 和 0x7F-0x9F 在 ISO-8859-1 中未定义(0x00 值得商榷,因为它通常用作空终止符),以及 UTF-8 中的大多数非 ASCII 字节由于 UTF-8 对其位的编码方式,属于后者。
标签: .net unicode utf-8 character-encoding