如何读取包含特殊字符的ANSI编码文件

时间:2009-09-16 10:00:35

标签: c# encoding ansi

我正在编写TFS Checkin策略,该策略检查我们的源文件是否包含我们的文件头。

我的问题是,我们的文件头包含一个特殊字符“©”,不幸的是我们的一些源文件是用ANSI编码的。 因此,如果我在策略中阅读这些文件,则字符串看起来像“Copyright 2009”。

string content = File.ReadAllText(pendingChange.LocalItem);

我厌倦了改变字符串的编码,但它没有帮助。那么如何阅读这些文件,我得到正确的字符串“Copyright©2009”?

感谢您的帮助!

关心恩伊

3 个答案:

答案 0 :(得分:118)

使用Encoding.Default

string content = File.ReadAllText(pendingChange.LocalItem, Encoding.Default);

但是,您应该知道,它使用系统默认编码来读取它 - 这可能与文件的编码不同。没有单一的编码称为ANSI,但通常是,当人们谈论“ANSI编码”时,他们指的是Windows代码页或者他们的盒子碰巧使用的。

如果您能找到所使用的完全编码,您的代码将更加强大。

答案 1 :(得分:5)

如果你有这样的政策,你也会有团队认可的标准编码,这似乎是明智的。说实话,我不明白为什么任何团队都会使用除“Unicode(带签名的UtF-8) - 代码页65001”以外的编码(除非ASPX页面具有显着的非拉丁静态内容,但即便如此我也可以'看看使用UTF-8是多么重要。

假设您仍然希望允许混合编码,那么您接下来需要一种方法来确定保存文件的编码,以便您知道要传递给ReadAllText的编码。从文件中确定这一点并不容易,但使用Encoding.Default可能会正常工作。因为它很可能只有2个编码来处理,VS(带签名的UTF-8)和你的机器使用的常见ANSI编码(可能是Windows-1252)。

因此使用

 string content = File.ReadAllText(pendingChange.LocalItem, Encoding.Default);

会奏效。 (正如我看到Jon已经发布的那样)。这是有效的,因为当UTF-8 BOM(这是VS的术语“签名”)在文件的开头出现时,忽略提供的编码参数,无论如何都使用UTF-8。因此,在使用UTF-8保存文件的位置,您可以获得正确的结果,并且在使用ANSI的情况下,您很可能也能获得正确的结果。

顺便说一句,如果您正在处理文件头,ReadAllLines会不会让事情变得更容易?

答案 2 :(得分:0)

我知道这是一个老问题,但我遇到了类似的情况,发现公认的答案是在偷工减料(不考虑乔恩·斯基特务实的简短回答,但我会再充实一点)。 .

specs 声明标头将直接包含在 {\rtf: 之后的编码

 \ansi  ANSI (the default)
 \mac   Apple Macintosh
 \pc    IBM PC code page 437 
 \pca   IBM PC code page 850, used by IBM Personal System/2 (not implemented in version 1 of Microsoft Word for OS/2)

根据维基百科,“ANSI character set has no well-defined meaning

对于默认的 ANSI,您可以选择这些 partially incompatible 编码:

using System.Text;
...
string content = File.ReadAllText(filename, Encoding.GetEncoding("ISO-8859-1"));
or
string content = File.ReadAllText(filename, Encoding.GetEncoding("Windows-1252"));

在 Windows 10 上使用写字板保存带有欧元符号的文件(Windows-1252 中为 0x80,ISO-8859-1 中为 0xA4)显示以下内容:

标头在 \ansi

之后说明了确切的编码
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1043{ ...

并且没有直接使用编码,而是封装在 RTF 编码中:\'80

根据规格:

<块引用>

\'hh :十六进制值,基于指定的字符集(可能 用于识别 8 位值)。

我想最好的做法是阅读标题,如果文件以 {\rtf1\ansi\ansicpg1252 开头,则选择 Windows-1252

但为了让事情变得更复杂,the specs 还声明可能存在混合编码...搜索 '\upr'...

我想没有明确的答案,在您的情况下,最简单的方法可能是搜索(在未解码的原始字节数组中)您可能在源代码库中遇到的编码版权标志的所有变体.

就我而言,我最终决定也削减一些角落,但添加一小部分防御性编码。到目前为止,我看到的所有文件都是 Windows-1252,因此我对此进行了通用案例优化。

    Encoding encoding = Encoding.GetEncoding("Windows-1252", EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback);
    
    using (System.IO.StreamReader reader = new System.IO.StreamReader(filename, encoding)) {
        string header= reader.ReadLine();
        if (!header.Contains("cpg1252")) {
            if(header.Contains("\\pca"))
                encoding = Encoding.GetEncoding(850, EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback);
            else if (header.Contains("\\pc"))
                encoding = Encoding.GetEncoding(437, EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback);
            else
                encoding = Encoding.GetEncoding("ISO-8859-1", EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback);
        }
    }
    
    string content = System.IO.File.ReadAllText(filename, encoding);