我知道这是一个老问题,但我遇到了类似的情况,并发现公认的答案是偷工减料(不要忽视 Jon Skeet 务实的简短回答,但我会再充实一点)......
规范声明标头将在之后直接包含编码{\rtf:
\ansi ANSI(默认)
\mac 苹果麦金塔
\pc IBM PC 代码页 437
\pca IBM PC 代码页 850,由 IBM Personal System/2 使用(未在 Microsoft Word for OS/2 版本 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"));
在 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
.
但是为了让事情变得更复杂,规范还声明可以混合编码......搜索'\ 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);