【问题标题】:.NET Stream Decoders behavior.NET 流解码器行为
【发布时间】:2009-07-01 22:55:40
【问题描述】:

我有一个尝试从二进制流中解码不同编码的字符串的过程。当我逐步完成它时,我得到了一些在我脑海中并没有完全加起来的行为。具体来说,我要做的是:

  • 获取用于在给定编码中对字符进行编码的最大字节数
  • 从流中获取字节数
  • 使用Encoding.GetCharCount 来确定在这些字节中可能编码了多少个字符(可能是 0 一个或两个...)
  • 如果它不为零,我使用Encoding.GetString 从字节数组中抓取字符
  • 然后我计算出用于对提取的字符进行编码的字节数并将流索引推进该数量
  • 如果可解码字节数为零,我将索引前移一个字节并再次尝试整个过程...以这种方式,我希望不会错过任何可解码字符

顺便说一句,如果有人注意到上述任何不正确的假设,请随意说...

当我的解码器无法解码给定的一组字节时,我将它们设置为抛出DedcoderFallbackExceptions。让我感到困惑的是,有时当我调用GetCharCount 时会出现异常,而有时当我调用GetString 时会出现异常。有什么理由应该发生这种情况吗?这实际上是预期的吗?我希望能够在尽可能少的地方可靠地检查可打印字符的存在 - 目前我正在几个地方进行检查。

有什么想法吗?

谢谢, 布莱恩

重大更新: 看来我对这个问题的初步描述有点欠缺。让我为这个问题添加几个前提:

  • 流可能非常很大 - 它不会适合大多数用户的内存
  • 在流​​中的任何给定位置,我都不确定我是否在文本的开头,在文本的中间
  • 在流​​中的任何给定位置,我不知道我是在多字节字符的中间还是开头
  • 流将包含许多实际上不是任何类型的文本的材料,以及少量不同的编码

希望这可以澄清一些问题。到目前为止的回复非常有帮助!请继续!

【问题讨论】:

  • 我真的不明白你为什么要这样做。如果可能,最有效的方法是将整个内容读入内存并一次性处理。

标签: .net unicode stream binary-data decoding


【解决方案1】:

UTF8 等编码对字符使用可变字节数,因此您不能简单地乘以从流中获取的最大字节数。最后一个字节可能位于字符的中间(并且可能单独无效),或者最后一个字符可能代表该特定编码上完全不同的字符。

【讨论】:

  • 很好的一点 - 我想我已经解决了这个问题,虽然我没有在我的原始帖子中提到任何这些......我会详细说明。
  • 嗯,现在我想起来了,我似乎可能错误地解码了看起来像文本但实际上只是巧合的材料,此时我的偏移量不正确,对吧?有没有办法解决这个问题?
  • 可能。它可能发生取决于编码。为了安全地执行此操作,您应该在它们前面加上字节数和编码。如果字节看起来也像另一种编码中的有效文本并且您先尝试了那个怎么办?
  • 首先,我不是执行初始编码的人,所以我必须假设当我得到它时数据或多或少是完整的。其次,我可以在相同的字节块上尝试不同的编码,但是我该怎么办 - 看看哪个解码的字符最多?
  • 确实总是有出错的余地。例如,Web 浏览器使用启发式方法来检测编码,但就我个人而言,我曾多次遇到错误的编码检测并在网页上显示废话,不得不手动设置该页面的编码。事实上,编码就像一个合同。你应该在沟通之前就同意一个。否则,它会归结为猜测(这根本不容易,你应该使用库),但仍有出错的余地。
【解决方案2】:

哇。听起来像强大的矫枉过正。您是否尝试过使用编码的 GetDecoder 方法?它为您提供一个带有 GetChars 方法的解码器,您将一个字节数组和一个字符数组提供给该方法,并使用从字节数组解码的可用字符填充字符数组。

如果有任何过冲(即备用字节),这些将保存在解码器的状态中,以供您下次使用新字节调用 GetChars 时使用。

您可以使用 StringBuilder 来组装结果。

比你的方法简单一点。

【讨论】:

  • 不幸的是,我不这么认为。我不知道文本的开头,也不知道任何给定位置的实际编码。我认为这会阻止我使用 GetEncoding,对吗?
【解决方案3】:

如果我正确理解您的问题,您是否尝试从未知编码的字节流中读取字符数据?

如果我的假设是正确的,那么你需要先检测编码,然后使用TextReader以这种编码读取读取的字节流,那么你就不用担心不同的字符大小,TextReader会为你做所有的工作。

我知道两种从字节流中检测编码的方法:

  1. Ude is a C# port of Mozilla Universal Charset Detector.
  2. IE MultiLang services

【讨论】:

  • 你的假设确实是正确的。我将尽快查看您发布的库。可能需要几天时间,但如果可行,我会回来查看并更新主题。
  • 其实我自己没用过Ude,因为一个月前才发现。但是 MultiLang 非常适合我。不过我建议首先尝试 Ude,因为这是完全托管的解决方案。
  • 刚刚使用网站上提供的示例代码和一个非常简单的 .txt 文件作为输入流尝试了 UDE。它无法弄清楚编码。我还尝试了一个同样缺乏结果的 docx 文件...
  • 它似乎只适用于网站(即打开网站,下载页面,将其作为文件流打开并将其用作输入)。虽然这很酷,但它仍然不能解决问题。不过绝对值得一试。
猜你喜欢
  • 1970-01-01
  • 2017-02-09
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多