8

我有一个网络应用程序,允许用户上传他们的内容进行处理。处理引擎需要 UTF8(我正在从多个用户的文件中组合 XML),所以我需要确保我可以正确解码上传的文件。

因为如果我的任何用户知道他们的文件甚至编码,我会感到惊讶,我几乎不希望他们能够正确指定要使用的编码(解码器)。因此,我的应用程序的任务是在解码之前进行检测。

这似乎是一个普遍的问题,我很惊讶没有找到解决方案的框架功能或通用配方。可能是我没有使用有意义的搜索词进行搜索吗?

我已经实现了 BOM 感知检测(http://en.wikipedia.org/wiki/Byte_order_mark),但我不确定文件将多久上传一次 w/oa BOM 以指示编码,这对大多数非 UTF 文件。

我的问题归结为:

  1. 对于绝大多数文件来说,BOM 感知检测是否足够?
  2. 在 BOM 检测失败的情况下,是否可以尝试不同的解码器并确定它们是否“有效”?(我的尝试表明答案是“不”。)
  3. 在什么情况下,C# 编码器/解码器框架的“有效”文件会失败?
  4. 是否有任何地方的存储库包含大量具有各种编码的文件以用于测试?
  5. 虽然我专门询问 C#/.NET,但我想知道 Java、Python 和其他语言的答案,以便下次我必须这样做。

到目前为止,我发现:

  • 具有 Ctrl-S 字符的“有效”UTF-16 文件导致编码为 UTF-8 引发异常(非法字符?) (这是 XML 编码异常。)
  • 使用 UTF-8 解码有效的 UTF-16 文件会成功,但会给出带有空字符的文本。嗯?
  • 目前,我只期望 UTF-8、UTF-16 和可能的 ISO-8859-1 文件,但如果可能的话,我希望解决方案是可扩展的。
  • 我现有的输入文件集还不够广泛,无法发现实时文件会出现的所有问题。
  • 尽管我尝试解码的文件是“文本”,但我认为它们通常是使用在文件中留下垃圾字符的方法创建的。因此“有效”文件可能不是“纯”文件。哦快乐。

谢谢。

4

5 回答 5

3

不会有绝对可靠的方法,但您可以通过一些启发式方法获得“相当不错”的结果。

  • 如果数据以 BOM 开头,请使用它。
  • 如果数据包含 0 字节,则可能是 utf-16 或 ucs-32。您可以通过查看 0 字节的位置来区分这些,以及它们的大端和小端变体
  • 如果数据可以解码为 utf-8(没有错误),那么很可能是 utf-8(或 US-ASCII,但这是 utf-8 的子集)
  • 接下来,如果您想走向国际化,请将浏览器的语言设置映射到该语言最可能的编码。
  • 最后,假设 ISO-8859-1

当然,“相当好”是否“足够好”取决于您的应用程序。如果您需要确定,您可能希望将结果显示为预览,并让用户确认数据看起来正确。如果没有,请尝试下一个可能的编码,直到用户满意为止。

注意:如果数据包含垃圾字符,此算法将不起作用。例如,原本有效的 utf-8 中的单个垃圾字节将导致 utf-8 解码失败,从而使算法走错路。您可能需要采取额外措施来处理此问题。例如,如果您可以事先识别可能的垃圾,请在尝试确定编码之前将其剥离。(剥离过于激进也没关系,一旦确定了编码,就可以解码原始未剥离的数据,只需配置解码器替换无效字符而不是抛出异常。)或者统计解码错误并适当加权. 但这可能很大程度上取决于你的垃圾的性质,即你可以做出什么样的假设。

于 2010-02-22T21:16:09.197 回答
2

您是否尝试过从用户那里读取文件的代表性横截面,通过您的程序运行它们,测试,纠正任何错误并继续前进?

我发现 File.ReadAllLines() 在非常广泛的应用程序中非常有效,而无需担心所有编码。它似乎处理得很好。

一旦我弄清楚如何正确使用它,Xmlreader() 就做得很好了。

也许您可以发布一些具体的数据示例并获得更好的响应。

于 2010-02-22T21:03:31.103 回答
1

您可能想查看一个名为chardet的基于 Python 的解决方案。它是 Mozilla 代码的 Python 端口。尽管您可能无法直接使用它,但它的文档非常值得一读,就像它引用的原始 Mozilla 文章一样。

于 2010-03-08T01:35:58.263 回答
1

这是一个众所周知的问题。您可以尝试执行 Internet Explorer 正在执行的操作。这是 The CodeProject 中的一篇很好的文章,描述了 Microsoft 对问题的解决方案。然而,没有任何解决方案是 100% 准确的,因为一切都是基于启发式的。并且假设 BOM 将存在也是不安全的。

于 2010-02-22T21:04:28.700 回答
0

我遇到了类似的问题。我需要一个 powershell 脚本来确定文件是否是文本编码的(以任何常见的编码)。

这绝对不是详尽无遗,但这是我的解决方案......

忽略二进制文件的 PowerShell 搜索脚本

于 2010-03-08T01:41:25.230 回答