File.Copy和字符编码

时间:2009-06-16 08:45:37

标签: c# .net file-io

我注意到.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混淆

2 个答案:

答案 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,它们是否相同?