C#: 有没有办法发现一个文件正在使用的字符集编码?

3
有没有办法发现一个文件使用的字符集编码是什么?
7个回答

4
唯一可靠的方法是在文本文件开头查找字节序标记。(此 blob 更普遍地表示所使用的字符编码的字节顺序,但也表示编码方式 - 例如UTF8、UTF16、UTF32)。不幸的是,这种方法仅适用于基于Unicode的编码,而不适用于更早的编码(必须使用不太可靠的方法)。 StreamReader 类型支持检测这些标记以确定编码 - 您只需要向参数传递一个标志即可:
new System.IO.StreamReader("path", true)

您可以检查 stremReader.CurrentEncoding 的值来确定文件使用的编码方式。请注意,如果没有字节编码标记存在,则 CurrentEncoding 将默认为 Encoding.Default

这对所有可能的编码方式都适用吗?包括Unicode之前的编码方式? - Valentin V
如果像大多数传统编码一样,没有字节顺序标记,那么你就会被雨淋湿了... - Artelius
1
@Valentin:恐怕这只能区分Unicode编码。通常情况下,它被认为是ANSI编码。 - Noldorin
请注意,这里的“ANSI”具有非常特定的含义,与美国国家标准无关,即“此Windows安装的默认代码页”。可能是CP1252,也可能是其他内容。 - MSalters

3

请看这个:在.NET中检测文件编码

来自Msdn

没有一种好的方法可以检测任意的ANSI代码页,虽然有一些尝试基于文本中某些字节序列的概率进行检测。我们在StreamReader中不会尝试这样做。一些如XML或HTML之类的文件格式在文件的第一行上指定了字符集的方式,因此Web浏览器、数据库和像XmlTextReader这样的类可以正确地读取这些文件。但许多文本文件没有内置这种类型的信息。


0

为了增加潜在有用的链接列表,这里是一个我编写的相当小的类,用于检测Unicode编码(带或不带BOM)与默认代码页(通常是Windows-1252,在.Net中标记为Encodings.ASCII的“ASCII”)之间的区别:

http://www.architectshack.com/TextFileEncodingDetector.ashx

它比StreamReader的默认功能更进一步,基本上就是@peterchen在他上面的回答中描述的内容,只不过这个是C#代码:

  • 首先检查BOM,如果提供了就使用它
  • 否则,检查文件可能的Unicode编码。
  • 对于找到的每种可能的Unicode编码,检查该编码是否适用于提供的数据(假设主要是西欧内容)
  • 如果“可能”的Unicode编码看起来不太可能,就使用提供的默认代码页/编码

很抱歉这个答案来得这么晚 - 我最近才整理了这个类并将其放在线上。


0

没有一种方法可以100%可靠地完成这个任务。您必须决定哪些成本与准确性的权衡是您可以接受的。我在这篇回复中讨论了许多可能的算法(包括优缺点):忽略二进制文件的PowerShell搜索脚本


0

0

我之前用C++编写了这个程序,它变得相当复杂。以下是我的做法(接受第一个匹配项):

  • 查找字节顺序标记
  • 检查文本是否为有效的UTF-32 BE/LE
  • 检查文本是否为有效的UTF-16 BE/LE
  • 检查文本是否为有效的UTF-8
  • 假设当前代码页

这可以处理许多没有BOM的文本文件,但无法帮助处理使用自定义ANSI代码页存储的文本。

对于这些情况,无法进行确定性检测。例如,使用“东欧”编码保存的文件,在默认代码页为“西欧”的计算机上加载将会出现乱码。

在这种情况下唯一可能的帮助方式是让用户选择代码页(从用户体验的角度来看,最好让用户在查看文本时更改假定的编码)。

它在测试集上运行良好,但当然可能会出现误解,尽管不太可能。

编码页可以通过对文本进行统计分析来确定(例如,包含非ASCII字符的字符对和三元组的频率,或不同语言的单词列表),但我尝试了一些方法都没有找到合适的方法。

Win32 IsTextUnicode 非常糟糕,它只检查UTF-16,并且很可能是记事本中“bush hid the facts”问题的罪魁祸首。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接