【问题标题】:Is it possible to reliably auto-decode user files to Unicode? [C#]是否可以可靠地将用户文件自动解码为 Unicode? [C#]
【发布时间】:2011-01-19 19:48:11
【问题描述】:

我有一个网络应用程序,允许用户上传他们的内容进行处理。处理引擎需要 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 文件,但如果可能,我希望解决方案可以扩展。
  • 我现有的输入文件集不够广泛,无法发现实时文件会出现的所有问题。
  • 虽然我试图解码的文件是“文本”,但我认为它们通常是使用在文件中留下垃圾字符的方法创建的。因此“有效”文件可能不是“纯”文件。哦,快乐。

谢谢。

【问题讨论】:

  • 是什么让您认为 UTF-8 和 UTF-16 兼容?一个以单字节块存储数据,另一个以 2 字节块存储数据......
  • BOM 主要用于 Microsoft 操作系统,Unices 更喜欢没有 BOM 的编码。
  • 是否允许使用Ctrl-S 字符,与您的格式无关。 UTF-8 和 UTF-16 都能够编码Ctrl-S,只是对于软件(使用获得的 UTF-8)这个字符可能是意外的。
  • 如果你解码一个 UTF-16 文件就像它是 UTF-8,当然你会在每个第二个字节得到空字符。故事是字符0 以UTF-8 编码为字节0x30,但在UTF-16 中编码为两个字节0x30 0x00 (0x0030)。
  • @Matthew:您是否建议我可以在同一个 XML 文件中混合使用 UTF-8 和 UTF-16 编码的字符串? @Vlad - 它不是任何特定的软件死了它实际上是 C# 核心 System.Xml.Linq.XElement.WriteTo(XmlWriter) 抛出异常的方法(虽然代码已经改变所以我无法通过大量工作重现错误)。

标签: c# string utf-8 multilingual utf-16


【解决方案1】:

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

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

PowerShell search script that ignores binary files

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • FWIW,我抓住了 UDE [code.google.com/p/ude/] 用 Mono 编译它。然后我针对编码为 ISO-8859-1、-2、UTF-{8,16LE,16BE,32LE,32BE} 的文件运行生成的 EXE,它只正确识别 UTF-8(猜测是 windows-1255 或 -1252其他一切)。
    • 它不会识别没有 BOM 的 UTF-nnxE;你的有BOM吗? ISO-8859-n 是虚构的——将其解码为 Unicode,看看是否有 U+0080 到 U+009F 范围内的任何字符;-)
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 这很有帮助,不过请注意,我已通过 C#/.NET 编码框架毫无例外地解码了一些 UTF16LE 文件;有错误(空字符)但没有异常。我的意图是自动检测(因此发布)并且我已经部分实现了它,因为我已经检测到 MSWord、PDF 和其他非文本文件,但问题是确定何时编码是 正确一。
    • 你说得对,0字节检查需要先进行,我相应地修复了我的答案中的步骤顺序
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

      一旦我弄清楚如何正确使用它,Xmlreader() 就做得相当不错了。

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

      【讨论】:

      • 谢谢,但我正在寻找通用解决方案。在此应用程序中,该应用程序部署在客户的站点上,我无权访问(或合法许可)这些文件。它们是用户希望上传的任何文本文档。有些是 PDF 转文本,有些是从网站上抓取的,有些是 PPT 幻灯片,有些是……谁知道呢。
      • 那么我会说确保你有关于输入/输出等的大量日志记录到用户本地事件日志中。对我来说,这听起来像是一个双赢的局面。
      • 顺便说一句,我不明白你所说的纠正任何错误并继续前进的意思——我无法“纠正”用户的文件,而我现在遇到的错误是他们必须正确选择编码格式。我会调查 File.ReadAllLines()...
      • File.ReadAllLines() 的编码检测功能是否可用于 Streams?
      猜你喜欢
      • 2012-09-12
      • 2016-11-01
      • 2019-02-26
      • 1970-01-01
      • 2011-08-28
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 2016-04-11
      相关资源
      最近更新 更多