2009-06-16 85 views
0

我注意到了.NET 3.5SP1中File.Copy()的奇怪行为。我不知道这是一个错误还是一个功能。但我知道这让我发疯。我们在自定义构建步骤中使用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混乱

回答

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,小端 Unicode和大端Unicode文本 。有关更多 信息,请参阅 Encoding.GetPreamble方法。

现在File.Copy只是复制从一个地方的原始字节的地方 - 它不会改变任何东西字符编码方面,因为它不尝试将文件解释为在第一个文本文件地点。

我不太清楚你在哪里看到问题(部分归因于ANSI/ASCII部分)。我建议你分开“File.Copy改变事情吗?”的问题。和“StreamReader检测到什么字符编码?”在你的头脑和你的问题。这些问题的答案应该是:

  • File.Copy不应该更改文件的内容全部
  • StreamReader只能检测UTF-8和UTF-16;如果您需要读取使用任何其他编码进行编码的文件,则应该在构造函数中明确声明。 (我个人推荐使用Encoding.Default代替Encoding.GetEncoding(0)顺便说一下,我觉得它更清晰。)
+0

问题不在于StreamReader。我只用它来创建可以重现问题的一小段代码。 (我搞砸了,因为我在混淆ASCII和ANSI的同时玩弄它)。我首先在一个十六进制编辑器中注意到了它,并且据我了解,生成的文件不正确,因为它具有UTF-8字节顺序标记(开始时为3个字节),并且重音字符有错误的字符代码 – chris166 2009-06-16 09:20:42

+0

有些奇怪。我无法再现它。所以有些东西过时了(我的十六进制编辑器,VS中的代码或其他)。无论如何,感谢您研究这个问题并花费这么多时间! – chris166 2009-06-16 09:26:56

0

我怀疑这有什么关系File.Copy。我认为你所看到的是StreamReader默认使用UTF-8进行解码,而且由于UTF-8向后兼容,StreamReader永远不会有任何理由停止使用UTF-8来读取ANSI编码的文件。

如果在十六进制编辑器中打开ASCII.txt和copy.txt,它们是否相同?