GvS*_*GvS 292 .net c# globalization encoding text
在我们的应用中,我们收到的文本文件(.txt
,.csv
从不同的来源,等等).在阅读时,这些文件有时会包含垃圾,因为文件是在不同的/未知的代码页中创建的.
有没有办法(自动)检测文本文件的代码页?
的detectEncodingFromByteOrderMarks
,对StreamReader
构造,工程UTF8
和其他的Unicode标文件,但是我正在寻找一种方法来检测代码页,像ibm850
,windows1252
.
谢谢你的回答,这就是我所做的.
我们收到的文件来自最终用户,他们没有关于代码页的线索.接收者也是最终用户,到目前为止,这是他们对代码页的了解:代码页存在,并且令人讨厌.
解:
JV.*_*JV. 258
你无法检测代码页,需要告诉它.您可以分析字节并猜测它,但这可能会产生一些奇怪的(有时是有趣的)结果.我现在找不到它,但我确信记事本可以用中文显示英文文本.
无论如何,这是你需要阅读的内容: 绝对最低每个软件开发人员绝对必须知道Unicode和字符集(没有借口!).
特别是乔尔说:
关于编码的最重要事实
如果你完全忘记我刚才解释的一切,请记住一个非常重要的事实.在不知道它使用什么编码的情况下拥有字符串是没有意义的.你不能再把头埋在沙子里,假装"普通"文字是ASCII.没有像平原那样的东西.
如果您有字符串,内存,文件或电子邮件消息,则必须知道它所处的编码,或者您无法解释它或正确地将其显示给用户.
Tom*_*bel 31
如果您希望检测非UTF编码(即没有BOM),那么您基本上可以使用文本的启发式和统计分析.您可能需要查看有关通用字符集检测的Mozilla文章(相同链接,通过Wayback Machine更好地格式化).
ITm*_*eze 25
您是否尝试过使用Mozilla Universal Charset Detector的C#端口
来自http://code.google.com/p/ude/的示例
public static void Main(String[] args)
{
string filename = args[0];
using (FileStream fs = File.OpenRead(filename)) {
Ude.CharsetDetector cdet = new Ude.CharsetDetector();
cdet.Feed(fs);
cdet.DataEnd();
if (cdet.Charset != null) {
Console.WriteLine("Charset: {0}, confidence: {1}",
cdet.Charset, cdet.Confidence);
} else {
Console.WriteLine("Detection failed.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
sho*_*osh 15
您无法检测代码页
这显然是错误的.每个Web浏览器都有某种通用字符集检测器来处理没有任何编码指示的页面.Firefox有一个.您可以下载代码并查看它是如何做到的.在这里查看一些文档.基本上,它是一种启发式方法,但效果非常好.
给定合理数量的文本,甚至可以检测语言.
我知道这个问题已经很晚了,这个解决方案不会吸引一些人(因为它以英语为中心的偏见和缺乏统计/经验测试),但它对我来说非常有效,特别是对于处理上传的CSV数据:
http://www.architectshack.com/TextFileEncodingDetector.ashx
好处:
注意:我是那个写这个课程的人,所以很明显地把它当作一粒盐!:)
寻找不同的解决方案,我发现了
https://code.google.com/p/ude/
这个解决方案有点沉重.
我需要一些基本的编码检测,基于4个第一个字节和可能的xml字符集检测 - 所以我从互联网上采取了一些示例源代码并添加了略微修改后的版本
http://lists.w3.org/Archives/Public/www-validator/2002Aug/0084.html
为Java而写.
public static Encoding DetectEncoding(byte[] fileContent)
{
if (fileContent == null)
throw new ArgumentNullException();
if (fileContent.Length < 2)
return Encoding.ASCII; // Default fallback
if (fileContent[0] == 0xff
&& fileContent[1] == 0xfe
&& (fileContent.Length < 4
|| fileContent[2] != 0
|| fileContent[3] != 0
)
)
return Encoding.Unicode;
if (fileContent[0] == 0xfe
&& fileContent[1] == 0xff
)
return Encoding.BigEndianUnicode;
if (fileContent.Length < 3)
return null;
if (fileContent[0] == 0xef && fileContent[1] == 0xbb && fileContent[2] == 0xbf)
return Encoding.UTF8;
if (fileContent[0] == 0x2b && fileContent[1] == 0x2f && fileContent[2] == 0x76)
return Encoding.UTF7;
if (fileContent.Length < 4)
return null;
if (fileContent[0] == 0xff && fileContent[1] == 0xfe && fileContent[2] == 0 && fileContent[3] == 0)
return Encoding.UTF32;
if (fileContent[0] == 0 && fileContent[1] == 0 && fileContent[2] == 0xfe && fileContent[3] == 0xff)
return Encoding.GetEncoding(12001);
String probe;
int len = fileContent.Length;
if( fileContent.Length >= 128 ) len = 128;
probe = Encoding.ASCII.GetString(fileContent, 0, len);
MatchCollection mc = Regex.Matches(probe, "^<\\?xml[^<>]*encoding[ \\t\\n\\r]?=[\\t\\n\\r]?['\"]([A-Za-z]([A-Za-z0-9._]|-)*)", RegexOptions.Singleline);
// Add '[0].Groups[1].Value' to the end to test regex
if( mc.Count == 1 && mc[0].Groups.Count >= 2 )
{
// Typically picks up 'UTF-8' string
Encoding enc = null;
try {
enc = Encoding.GetEncoding( mc[0].Groups[1].Value );
}catch (Exception ) { }
if( enc != null )
return enc;
}
return Encoding.ASCII; // Default fallback
}
Run Code Online (Sandbox Code Playgroud)
它足以从文件中读取前1024个字节,但我正在加载整个文件.
如果有人正在寻找93.9%的解决方案.这对我有用:
public static class StreamExtension
{
/// <summary>
/// Convert the content to a string.
/// </summary>
/// <param name="stream">The stream.</param>
/// <returns></returns>
public static string ReadAsString(this Stream stream)
{
var startPosition = stream.Position;
try
{
// 1. Check for a BOM
// 2. or try with UTF-8. The most (86.3%) used encoding. Visit: http://w3techs.com/technologies/overview/character_encoding/all/
var streamReader = new StreamReader(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), detectEncodingFromByteOrderMarks: true);
return streamReader.ReadToEnd();
}
catch (DecoderFallbackException ex)
{
stream.Position = startPosition;
// 3. The second most (6.7%) used encoding is ISO-8859-1. So use Windows-1252 (0.9%, also know as ANSI), which is a superset of ISO-8859-1.
var streamReader = new StreamReader(stream, Encoding.GetEncoding(1252));
return streamReader.ReadToEnd();
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
287765 次 |
最近记录: |