【问题标题】:C# big-endian UCS-2C# 大端 UCS-2
【发布时间】:2011-10-21 17:52:12
【问题描述】:

我目前正在处理的项目需要与我们不制作的客户端系统交互,因此我们无法控制数据的发送方式。问题是在 C# 中工作,它似乎对 UCS-2 没有任何支持,对大端序的支持也很少。 (据我所知)

我想知道的是,是否有我在 .net 中查看过的内容,或者其他人制作并发布的我们可以使用的内容。如果没有,我会尝试用自定义方法对其进行编码/解码,如果可能的话。

但无论如何感谢您的时间。

编辑: BigEndianUnicode 确实可以正确解码字符串,问题在于接收其他数据作为大端,到目前为止,按照其他地方的建议使用 IPAddress.HostToNetworkOrder() 允许我解码字符串的一半(Merli?是什么出现了,应该是Merlin33069)

我正在梳理短代码,看看是否还有我错过的另一个长度变量

解决方案: 在确定 bigendian 变量是主要问题后,我回顾并查看了详细信息,似乎字符串的长度是以字符数而不是字节数发送的(在 utf 中,char 似乎是两个字节)我需要做的就是把它翻倍,它成功了。谢谢大家的帮助。

【问题讨论】:

  • 在大多数(不是全部)情况下,UCS-2 与 UTF-16 相同;你只是在寻找Encoding.BigEndianUnicode 吗?请注意,这实际上是 .NET 而不是 C#
  • 我强烈怀疑这个问题不是 UCS-2 和UTF-16 之间的区别。请提供一些示例数据来说明问题 - 显示原始字节,以及您期望解码后的文本是什么。
  • 好吧,我发现了问题,客户端在java中,我们这边是c#,所以当他们发送字符串时 length 它也是 bigendian,所以当我们在 c# 中得到不同的长度。
  • 所以现在的问题是弄清楚如何转换为发送/接收编辑我想我可以反转字节,对吧?
  • @Merlin 而不是 reversing 它们(在某些系统上可能不正确) - 我会简单地阅读它们并使用“移位”操作......将添加为答案

标签: c# .net endianness


【解决方案1】:

编辑:现在我们知道问题不在于文本数据的编码,而在于长度的编码。有几个选项:

  • 反转字节,然后使用内置的BitConverter 代码(我假设您现在正在使用它;或者BinaryReader
  • 使用重复的“添加和移位”操作自行执行转换
  • 使用来自MiscUtilEndianBitConverterEndianBinaryReader 类,类似于BitConverterBinaryReader,但让您指定字节顺序。

您可能正在寻找Encoding.BigEndianUnicode。那是大端 UTF-16 编码,严格来说与 UCS-2 不同(正如 Marc 所指出的那样),但应该没问题,除非你给它包含 BMP 之外的字符的字符串(即高于 U+FFFF) ,不能用 UCS-2 表示,但 用 UTF-16 表示。

来自Wikipedia page

较旧的 UCS-2(2 字节通用字符集)是一种类似的字符编码,在 1996 年 7 月的 Unicode 标准 2.0 版中被 UTF-16 取代。2 它通过以下方式生成固定长度格式只需将代码点用作 16 位代码单元,并且对于 0-0xFFFF 范围内的所有代码点的 96.9%(包括当时已分配值的所有字符)产生与 UTF-16 完全相同的结果。

我发现客户端系统极不可能向您发送有差异的字符(基本上是代理对,无论如何都是永久保留的)。

【讨论】:

  • 或在代理范围内。
  • @Ignacio:我不清楚你是在我编辑之前还是之后发表评论...你能再检查一下,看看是否还有什么要补充的吗?
  • 据我所知,所有文字都应该是普通字符。
  • @Merlin33069:那么我强烈怀疑问题不在你认为的地方。但是如果没有所涉及数据的具体示例,就很难说。
  • 以前,但它仍然存在; UCS-2 会将代理视为未知字符但有效的代码点,而 UTF-16 会在找不到合适的代理对时阻塞。
【解决方案2】:
string x = "abc";
byte[] data = Encoding.BigEndianUnicode.GetBytes(x);

另一个方向:

string decodedX = Encoding.BigEndianUnicode.GetString(data);

这不是完全正确 UCS-2 但对于大多数情况来说已经足够了。

UPD: Unicode FAQ

问:UCS-2 和 UTF-16 有什么区别?

答:UCS-2 是过时的术语,指的是 Unicode 最高 Unicode 1.1 的实现,在代理代码点和 UTF-16 被添加到标准的 2.0 版中。这个词现在应该 避免。

UCS-2 没有定义不同的数据格式,因为 UTF-16 和 UCS-2 出于数据交换的目的是相同的。两者都是 16 位的,并且具有 完全相同的代码单元表示。

过去,有时某个实现被标记为“UCS-2”以 表示它不支持补充字符并且不 将代理代码点对解释为字符。这样一个 实现不会处理字符属性的处理, 补充字符的代码点边界、排序规则等。

【讨论】:

  • 更好地解释 UCS-2 / UTF-16 ... UTF-16 Unicode 扩展 A 和 B。UCS-2 仅支持基本多语言平面 (BMP)。
【解决方案3】:

UCS-2 非常接近 UTF-16,Encoding.BigEndianUnicode几乎总是就足够了。

关于读取长度前缀(作为大端序)的问题(cmets)可以通过移位操作更正确地解决,这将在所有系统上执行正确的操作。例如:

Read4BytesIntoBuffer(buffer);
int len =(buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]); 

这将在 any 系统上以相同的方式工作(在解析大端 4 字节 int 时),无论本地字节序如何。

【讨论】:

    猜你喜欢
    • 2011-11-19
    • 1970-01-01
    • 2012-02-18
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 2016-07-09
    相关资源
    最近更新 更多