【问题标题】:Which encoding to use for reading a string from a file?使用哪种编码从文件中读取字符串?
【发布时间】:2011-05-11 21:01:06
【问题描述】:

我正在解析一个包含字符串的文件(我不生成该文件)。字符串前面总是有 2 个字节,告诉我后面的字符串的长度。

例如:

05 00 53 70 6F 72 74

应该是:

Sport

使用 C# BinaryReader,我使用以下方法读取字符串:

string s = new string(binaryReader.ReadChars(size));

有时会有奇怪的时髦角色似乎将流的位置推得比应有的更远。例如:

0D 00 63 6F 6F 6B 20 E2 80 94 20 62 6F 6F 6B

应该是:

cook - book

虽然它读得很好,但流最终比它应该的还要多两个字节?! (这会打乱其余的解析。)

我猜它与中间的 0xE2 有关,但我不确定为什么或如何处理它。

任何建议都非常感谢!

【问题讨论】:

  • 在得到了所有很好的答案之后,我用以下方法解决了它: byte[] b = binRdr.ReadBytes(size);字符串 s = Encoding.UTF8.GetString(b);事实上,这将无休止地改进我的解析器!谢谢大家!

标签: c# string encoding character-encoding binary-data


【解决方案1】:

我的猜测是字符串是用 UTF-8 编码的。 3 字节序列E2 80 94 对应于单个 Unicode 字符 U+2014 (EM DASH)。

【讨论】:

  • 嘿,泰德,谢谢你的回答。我期望的字符确实是 EM DASH,所以那将是 UTF8。所以用 UTF8 编码读取字符串应该可以解决它...
  • 来源是什么?我想知道,因为开头的长度并不常见。
  • @Jonas - 实际上,将序列化字符串作为长度加数据很常见(尽管我认为更常见的是计数指的是编码中的字节数,而不是逻辑字符)。它避免了检测字符串结尾的问题(并非所有环境都为此使用0 字节)。
  • 你说的完全正确,只是我不记得在文件中见过它。
  • 是的,为了清楚起见,前面的 2 个字节是一个 Int16,表示组成字符串的字节数,而不是字符数。
【解决方案2】:

在你的第一个例子中

05 00 53 70 6F 72 74

没有一个字节超过 0x7F,这恰好是 7 位 ASCII 的限制。 UTF-8 保留了与 ASCII 的兼容性,通过使用第 8 位来表示将有更多信息。

0D 00 63 6F 6F 6B 20 E2 80 94 20 62 6F 6F 6B

正如 Ted 注意到您的“问题”以 0xE2 开头,因为这不是 7 位 ASCII 字符。

第一个字节 0x0D 告诉我们应该有 11 个字符,但有 13 个字节。

0xE2 告诉我们,自从设置了最高有效位(超过 127)以来,我们已经找到了 UTF-8 序列的开头。在这种情况下,sequence 代表 - (EM Dash)。

【讨论】:

  • 太棒了,谢谢乔纳斯。认为你和泰德都是正确的。我仍在学习编码,但这是一个很好的教训。
【解决方案3】:

正如您正确指出的那样,E2 字符是问题所在。 BinaryReader.ReadChars(n) 不读取 n 字节,而是读取 n 个 UTF-8 编码的 Unicode 字符。参见维基百科Unicode Encodings。您所追求的术语是代理字符。在 UTF-8 中,000080 – 00009F 范围内的字符由两个字节表示。这就是您的偏移不匹配的原因。

您需要使用 BinaryReader.ReadBytes 来修复偏移问题并将其传递给 Encoding 实例。

要使其工作,您需要使用 BinaryReader 读取字节,然后使用正确的编码对其进行解码。假设您正在处理 UTF-8,那么您需要将字节数组传递给

Encoding.UTF8.GetString(byte [] rawData)

获取正确编码的字符串。

你的, 阿洛伊斯克劳斯

【讨论】:

  • 感谢阿洛伊斯的解释。在 Ted 和 Joans 的帮助下,我做到了,但你的“字节数”解释肯定有帮助。
  • 代理字符与此无关。这些是一种 Unicode 技术,用于将 U+FFFF(补充平面)之上的 Unicode 代码点表示为 BMP 中的两个 Unicode 字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-28
  • 2015-09-18
  • 2016-04-07
  • 2012-09-02
相关资源
最近更新 更多