【问题标题】:Conversion of a unicode character from byte从字节转换 Unicode 字符
【发布时间】:2010-10-08 02:41:19
【问题描述】:

在我们的 API 中,我们使用 byte[] 通过网络发送数据。一切正常,直到我们的“外国”客户决定传递/接收 Unicode 字符。

据我所知,Unicode 字符占用 2 个字节,但是,我们只在字节数组中为它们分配 1 个字节。

下面是我们从 byte[] 数组中读取字符的方法:

       // buffer is a byte[6553] and index is a current location in the buffer
        char c = System.BitConverter.ToChar(buffer, m_index);
        index += SIZEOF_BYTE;

        return c;

所以当我查看 Unicode 十六进制时,当前的问题是 API 正在接收一个奇怪的 Unicode 字符。我发现最后一个有效字节是正确的,但最高有效字节在它应该为 0 时有一个值。到目前为止,一个快速的解决方法是使用 0x00FF & c 来过滤 msb。

请建议处理来自套接字的 Unicode 字符的正确方法?

谢谢。

解决方案:

向乔恩致敬:

char c = (char) 缓冲区[m_index];

正如他所提到的,它起作用的原因是因为客户端 api 接收到一个只占用一个字节的字符,而 BitConverter.ToChar 使用了两个,因此在转换它时存在问题。我仍然对为什么它适用于某些角色而不是其他角色感到惊讶,因为它应该在所有情况下都失败。

谢谢大家,很好的回应!

【问题讨论】:

  • “据我所知,Unicode 字符占用 2 个字节”这是错误的。最好的简化方法是认为“ASCII 已过时,文本字节流是 UTF8”,因此无论何时将它们从应用程序中取出/放入应用程序时,总是做一些编码/解码以在内部与 UTF8 进行转换。
  • 这种简化是错误的,因为它假定 UTF-8 无处不在——当然不是这样。是的,UTF-8 很常见,但假设它无处不在是错误的。最好的态度是根本不简化:在编码/解码时,您应该始终知道编码。不要假设。
  • 在这种情况下,我没有假设,因为我查看了服务器端代码,并看到它确实发送了一个打包在 1 个字节中的字符(没有任何编码)。尽管如此,我同意在编码/解码之前应该研究正确的编码。谢谢

标签: c# unicode types


【解决方案1】:

您应该使用Encoding.GetString,使用最合适的编码。

我不太了解你的情况,但Encoding 类几乎肯定是处理它的方法。

谁在控制这里的数据?您的代码,还是您客户的代码?你定义了正确的格式是什么?

编辑:好的,我再次查看了您的代码:BitConverter.ToChar 返回“由从 startIndex 开始的两个字节形成的字符。”如果您只想使用 一个 字节,只需转换它:

char c = (char) buffer[m_index];

我很惊讶你的代码一直在工作,因为它会在下一个字节非零时中断。

【讨论】:

  • 这可能有点棘手,因为我们还通过 str = System.Text.ASCIIEncoding.ASCII.GetString() 从网络接收字符串。也许,我误解了你的反应。你能给我举个例子吗?谢谢
  • 如果您使用 Encoding.ASCII,您将无法处理任何重音字符。我建议您在问题中提供更多信息。
【解决方案2】:

您应该查看 System.Text.ASCIIEncoder.ASCII.GetString 函数,该函数接受一个 byte[] 数组并将其转换为字符串(对于 ascii)。

对于 UTF8 或 UTF16 编码中的 Unicode 字符串,还有 System.Text.UTF8Encoder 或 System.Text.UTF16Encoder。

在 ASCIIEncoding、UTF8Encoding 和 UTF16Encoding 类中还有将字符串转换为 Byte[] 的函数:请参阅 GetBytes(String) 函数。

【讨论】:

    【解决方案3】:

    Unicode 字符最多可以占用 4 个字节,但很少在网络上对每个字符使用 4 个字节进行编码的消息。而是使用像 UTF8 或 UTF16 这样的方案,它们只在需要时引入额外的字节。

    查看Encoding 课程指南。

    【讨论】:

      【解决方案4】:

      测试流应该包含一个byte-order marker,它可以让您确定如何处理二进制数据。

      【讨论】:

        【解决方案5】:

        目前还不清楚您的目标到底是什么。据我所知,您可以选择 2 条路线

        1. 忽略以 Unicode 格式发送的所有数据
        2. 同时处理 unicode 和 ASCII 字符串

        恕我直言,#1 是要走的路。但听起来您的协议不一定设置为处理 unicode 字符串。您必须执行一些检测逻辑来确定传入的字符串是否是 Unicode 版本。如果是,您可以使用 Enconding.Unicode.GetString 方法来转换该特定字节数组。

        【讨论】:

          【解决方案6】:

          您的客户使用什么编码?如果您的一些客户仍在使用 ASCII,那么您将需要您的国际客户使用将 ASCII 集 (1-127) 映射到自身的东西,例如 UTF8。之后,使用 UTF8 编码的 GetString 方法。

          【讨论】:

            【解决方案7】:

            我唯一的解决方案是修复 API。要么告诉用户在 Byte[] 中只使用 ASCII 字符串,要么修复它以支持 ASCII 和您需要使用的任何其他编码。

            仅从 byte[] 确定外国客户端提供的编码可能有点棘手。

            【讨论】:

              猜你喜欢
              • 2012-11-30
              • 1970-01-01
              • 2019-08-15
              • 1970-01-01
              • 2013-08-21
              • 1970-01-01
              • 1970-01-01
              • 2018-04-29
              • 2021-11-16
              相关资源
              最近更新 更多