我注意到.NET 3.5SP1中File.Copy()
的奇怪行为。我不知道这是一个错误还是一个功能。但我知道这让我发疯了。我们在自定义构建步骤中使用File.Copy()
,它会搞砸字符编码。
当我通过UTF-8编码的文本文件复制ASCII编码文本文件时,目标文件仍然是UTF-8编码,但具有新文件的内容加上UTF-8的3个前缀字符。这对ASCII字符很好,但对ANSI代码页的剩余字符(128-255)不正确。
这是重现的代码。我首先将UTF-8文件复制到目标,然后将ANSI文件复制到同一目标。请注意第二个控制台输出的输出:Content of copy.txt : this is ASCII encoded: / Encoding: utf-8
File.WriteAllText("ANSI.txt", "this is ANSI encoded: é", Encoding.GetEncoding(0));
File.WriteAllText("UTF8.txt", "this is UTF8 encoded: é", Encoding.UTF8);
File.Copy("UTF8.txt", "copy.txt", true);
using (StreamReader reader = new StreamReader("copy.txt", true))
{
Console.WriteLine("Content of copy.txt : " + reader.ReadToEnd() + " / Encoding: " +
reader.CurrentEncoding.BodyName);
}
File.Copy("ANSI.txt", "copy.txt", true);
using (StreamReader reader = new StreamReader("copy.txt", true))
{
Console.WriteLine("Content of copy.txt : " + reader.ReadToEnd() + " / Encoding: " +
reader.CurrentEncoding.BodyName);
}
为什么会这样?我的代码中有错误吗?任何想法如何解决这个问题(我目前的想法是删除文件之前,如果它存在)
编辑:正确的ANSI / ASCII混淆
答案 0 :(得分:1)
你在哪里写ASCII.txt?你在第一行编写ANSI.txt,但肯定不是ASCII,因为ASCII不包含任何重音字符。 ANSI文件不包含任何前导码,表明它是ANSI而不是ASCII或UTF-8。
基本上,通过编写示例,您似乎已经在ASCII和ANSI之间改变了主意。
我希望任何ASCII文件都被“检测”为UTF-8,但编码检测依赖于具有字节顺序标记的文件,因为它不是UTF-8。它不像读取整个文件然后猜测编码是什么。
来自StreamReader的文档:
这个构造函数初始化了 编码为UTF8Encoding ,. 使用流的BaseStream属性 参数,以及内部缓冲区 默认大小。
detectEncodingFromByteOrderMarks 参数检测编码 看着前三个字节 流。它自动 识别UTF-8,little-endian Unicode和big-endian Unicode文本 如果文件以 适当的字节顺序标记。见 Encoding.GetPreamble方法更多 信息。
现在File.Copy
只是将原始字节从一个地方复制到另一个地方 - 它不应该在字符编码方面改变任何,因为它不会尝试将文件解释为首先是一个文本文件。
我不太清楚你在哪里看到问题(部分原因是ANSI / ASCII部分)。我建议你分开“File.Copy改变事情吗?”的问题。和“StreamReader检测到什么字符编码?”在你的思想和你的问题。答案应该是:
File.Copy
不应该改变文件的内容StreamReader
只能检测UTF-8和UTF-16;如果您需要读取使用任何其他编码编码的文件,您应该在构造函数中明确说明。 (我个人建议顺便使用Encoding.Default
而不是Encoding.GetEncoding(0)
。我认为它更清楚。)答案 1 :(得分:0)
我怀疑这与File.Copy有什么关系。我认为你所看到的是StreamReader默认使用UTF-8进行解码,因为UTF-8是向后兼容的,所以StreamReader没有任何理由停止使用UTF-8来读取ANSI编码的文件。
如果在十六进制编辑器中打开ASCII.txt和copy.txt,它们是否相同?