如何检测文本文件的编码/代码页
在我们的应用程序中,我们从各种来源接收文本文件(.txt,.csv等)。读取时,这些文件有时包含垃圾,因为这些文件是在不同/未知的代码页中创建的。
有没有办法(自动)检测文本文件的代码页?
在StreamReader构造函数上的detectEncodingFromByteOrderMarks可用于UTF8和其他带有unicode标记的文件,但是我正在寻找一种检测代码页的方法,例如ibm850和windows1252.
感谢回答,这就是我所做的。
我们收到的文件来自最终用户,他们不了解代码页。接收者也是最终用户,到目前为止,这是他们对代码页的了解:代码页存在并且令人讨厌。
解决方案:
- 在记事本中打开收到的文件,查看乱码的文本。如果有人叫Fran?ois之类的东西,凭着智慧,我们就可以猜到。
- 我创建了一个小应用程序,用户可用来打开文件,并输入一个文本,用户知道使用正确的代码页时它将出现在文件中。
- 循环浏览所有代码页,并使用用户提供的文本显示提供解决方案的代码页。
- 如果弹出一个以上的代码页,请要求用户指定更多文本。
解决方案
StreamReader类的构造函数采用"检测编码"参数。
如果我们要检测非UTF编码(即没有BOM),则基本上可以进行文本的启发式和统计分析。我们可能想看一下有关通用字符集检测的Mozilla论文(相同的链接,通过Wayback Machine进行更好的格式化)。
遇到了同样的问题,但尚未找到能够自动检测的好的解决方案。
现在,我为此使用PsPad(www.pspad.com);)
我们无法检测到代码页,需要告知它。我们可以分析字节并进行猜测,但这可能会带来一些奇怪(有时很有趣)的结果。我现在找不到它,但是我敢肯定,记事本可以被欺骗来显示中文的英文文本。
无论如何,这是我们需要阅读的内容:
每个软件开发人员绝对,肯定必须绝对了解Unicode和字符集(无借口!)。
特别是乔尔说:
The Single Most Important Fact About Encodings If you completely forget everything I just explained, please remember one extremely important fact. It does not make sense to have a string without knowing what encoding it uses. You can no longer stick your head in the sand and pretend that "plain" text is ASCII. There Ain't No Such Thing As Plain Text. If you have a string, in memory, in a file, or in an email message, you have to know what encoding it is in or you cannot interpret it or display it to users correctly.
我在Python中做了类似的事情。基本上,我们需要大量来自各种编码的样本数据,这些数据通过一个滑动的两字节窗口分解并存储在字典(哈希)中,并以提供编码列表值的字节对为关键字。
给定该字典(哈希),我们将输入文本并:
- 如果它以任何BOM字符开头(对于UTF-16-BE为'\ xfe \ xff',对于UTF-16-LE为'\ xff \ xfe',对于UTF-8为'\ xef \ xbb \ xbf等),我按建议对待
- 如果不是,则获取足够大的文本样本,获取样本的所有字节对,然后从字典中选择最不常用的编码。
如果我们还对不以任何BOM开始的UTF编码文本进行了采样,则第二步将覆盖从第一步开始遗漏的文本。
到目前为止,它对我有用(示例数据和后续输入数据是各种语言的字幕),并且出错率不断降低。
You can't detect the codepage
这显然是错误的。每个网络浏览器都有某种通用的字符集检测器来处理没有任何编码指示的页面。 Firefox有一个。我们可以下载代码,并查看其工作方式。请参阅此处的一些文档。基本上,这是一种启发式方法,但是效果很好。
给定合理的文本量,甚至可以检测语言。
这是我刚刚使用Google找到的另一个:
由于它基本上可以归结为试探法,因此可以将来自同一来源的先前接收的文件的编码用作第一提示。
大多数人(或者应用程序)每次都在同一台机器上以几乎相同的顺序执行操作,因此很有可能当Bob创建.csv文件并将其发送给Mary时,它将始终使用Windows-1252或者无论他的机器默认为什么。
在可能的情况下,一点点的客户培训也不会伤害任何一个:-
Notepad ++具有开箱即用的功能。它还支持更改它。
我实际上正在寻找一种检测文件编码的通用而不是编程的方法,但是我还没有找到。
通过使用不同的编码进行测试,我发现我的文字是UTF-7.
所以我首先在哪里:
StreamReader文件= File.OpenText(完整文件名);
我不得不将其更改为:
StreamReader文件=新的StreamReader(完整文件名,System.Text.Encoding.UTF7);
OpenText假定它是UTF-8.
我们也可以像这样创建StreamReader
new StreamReader(fullfilename,true),第二个参数意味着它应该尝试从文件的字节顺序标记中检测编码,但是在我的情况下不起作用。