.net System.IO.File.ReadAllText未引发无效编码异常
我在一个文件中有一些UTF-8文本.net System.IO.File.ReadAllText未引发无效编码异常,.net,unicode,utf-8,character-encoding,.net,Unicode,Utf 8,Character Encoding,我在一个文件中有一些UTF-8文本utf8.txt。该文件包含一些超出ASCII范围的字符。我尝试了以下代码: var fname = "utf8.txt"; var enc = Encoding.GetEncoding("ISO-8859-1", EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); var s = System.IO.File.ReadAllText(fname, enc); v
utf8.txt
。该文件包含一些超出ASCII范围的字符。我尝试了以下代码:
var fname = "utf8.txt";
var enc = Encoding.GetEncoding("ISO-8859-1", EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
var s = System.IO.File.ReadAllText(fname, enc);
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);
预期的行为是代码应该抛出异常,因为它不是有效的ISO-8859-1文本。相反,其行为是将UTF-8文本正确解码为正确的字符(在调试器中看起来是正确的)
这是.Net
中的错误吗
编辑:
我最初使用的文件是带有BOM的UTF-8。如果删除BOM表,行为将发生更改。它仍然不会引发异常,但会生成不正确的Unicode字符串(该字符串在调试器中看起来不正确)
编辑:
要生成测试文件,请运行以下代码:
var fname = "utf8.txt";
var enc = Encoding.GetEncoding("ISO-8859-1", EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
var s = System.IO.File.ReadAllText(fname, enc);
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,则
将完全忽略传入的编码,并(正确地)将文件解码为UTF-8。(我没有测试如果BOM是谎言,文件不是真正的UTF-8会发生什么)我不同意这种行为。我认为.Net应该抛出一个异常,或者使用我给它的编码ReadAllText
- 如果文件没有BOM,.Net没有简单(100%可靠)的方法来确定文本不是真正的ISO-8859-1,因为大多数(全部?)UTF-8文本也是有效的ISO-8859-1,尽管是胡言乱语。所以它只是按照你的指令,用你给它的编码对文件进行解码。(我同意这种行为)
This method attempts to automatically detect the encoding of a file based on the presence of byte order marks.
我同意你的观点,这种行为非常愚蠢。我更喜欢
ReadAllBytes
并通过编码.GetString
手动检查它。你能提供一个你认为有问题的文件中的文本样本吗?我想了一下,但最好的方法是什么?我真的想发布一个二进制文件e、 也许只是一些你认为会失败的字符编码,我们可以在此基础上重新创建文本?或者我可以出去找一些模糊的utf8文本并使用它。我假设它不是一个特定的字符,只是你关心的任何无效ISO-8859-1字符都是8位编码,所以我相信字符允许从0x00到0xFF。“由于大多数(全部?)UTF-8文本也是有效的ISO-8859-1”-这仅适用于ASCII字节0x20-0x7E,它们在UTF-8和ISO-8859-1中相同。一旦超出该范围,UTF-8就不是有效的ISO-8859-1。ISO-8859-1中未定义字节0x00-0x1F和0x7F-0x9F(0x00是有争议的,因为它通常用作空终止符),而UTF-8中的大多数非ASCII字节由于UTF-8编码其位的方式而属于后一个范围。