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

Eny*_*yra 59 c# encoding ansi

我正在写一个TFS Checkin策略,它检查我们的源文件是否包含我们的文件头.

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

string content = File.ReadAllText(pendingChange.LocalItem);
Run Code Online (Sandbox Code Playgroud)

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

感谢帮助!

关心恩伊

Jon*_*eet 123

用途Encoding.Default:

string content = File.ReadAllText(pendingChange.LocalItem, Encoding.Default);
Run Code Online (Sandbox Code Playgroud)

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

如果您能找到所使用的确切编码,您的代码将更加强大.

  • 抱歉@JonSkeet,我没有意识到我正在评论你的答案(你在这里非常出名:-))。为了完成我之前的评论,.net core 1.0 中的属性“System.Text.Encoding.Default”不再返回 1252 代码页编码:而是生成“System.Text.UTF8Encoding.UTF8EncodingSealed”。据我所知,这种行为仅与“核心”框架和第五版本(即底层、核心)相关。祝你周末愉快 :-) (2认同)

Ant*_*nes 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);
Run Code Online (Sandbox Code Playgroud)

将工作.(正如我看到Jon已经发布的那样).这样做是因为当UTF-8 BOM(这是VS是指通过"签名"项)为存在于所提供的编码参数被忽略的文件和UTF-8的开始,则还是使用.因此,使用UTF-8保存文件的位置可以获得正确的结果,并且在使用ANSI的情况下,您最有可能获得正确的结果.

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


Lou*_*ers 5

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

规范规定标头将直接包含编码{\rtf:

\ansi ANSI(默认)
 \mac 苹果麦金塔电脑
 \pc IBM PC 代码页 437
 \pca IBM PC 代码页 850,由 IBM Personal System/2 使用(未在 OS/2 的 Microsoft Word 版本 1 中实现)

根据维基百科,“ ANSI 字符集没有明确定义的含义

对于默认 ANSI,您可以选择以下部分不兼容的编码:

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

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

标头说明了之后的确切编码\ansi

{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1043{ ...
Run Code Online (Sandbox Code Playgroud)

并且编码并没有直接使用,而是用RTF编码包裹起来:\'80

根据规格:

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

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

但为了让事情变得更复杂,规范还规定可以存在混合编码...搜索“\upr”...

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

就我而言,我最终决定也走捷径,但添加一小部分防御性编码。到目前为止我看到的所有文件都是Windows-1252针对常见情况进行优化的。

 \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)