C#大端UCS-2

3
我目前正在处理的项目需要与我们不控制的客户端系统进行接口,因此我们无法控制数据如何发送。问题是我们使用的是C#,它似乎没有对UCS-2提供任何支持,而对big-endian的支持非常少。(就我所知)
我想知道的是,.net中是否有我忽略的东西,或者其他人制作并发布了我们可以使用的东西。如果没有,我将尝试在自定义方法中对其进行编码/解码,如果可能的话。
但无论如何,感谢您的时间。
编辑: BigEndianUnicode可以正确解码字符串,问题在于接收其他数据时使用了big endian。到目前为止,使用IPAddress.HostToNetworkOrder()建议已经允许我解码一半的字符串(出现Merli?,实际应该是Merlin33069)。
我正在检查代码,看看是否有其他长度变量被忽略。
解决方案: 在弄清楚bigendian变量是主要问题之后,我回顾了细节,发现字符串的长度以字符计数方式发送,而不是字节计数方式(在utf中,似乎一个char是两个字节)。我只需要将其加倍,就可以解决问题了。谢谢大家的帮助。

2
在大多数情况下(并非全部情况),UCS-2与UTF-16相同;您是否只是寻找“Encoding.BigEndianUnicode”?请注意,这实际上是.NET而不是C#。 - Marc Gravell
我强烈怀疑问题并不是UCS-2和UTF-16之间的差异。请提供一些演示问题的样本数据 - 显示原始字节以及您期望解码的文本。 - Jon Skeet
我找到了问题所在,客户端是用Java编写的,而我们这边是用C#,所以当他们发送字符串“length”时,它也是大端字节序,因此当我们在C#中获取长度时就会有所不同。 - RyanTimmons91
所以现在的问题是想要弄清楚如何进行发送/接收时的转换。我想我只需要将字节反转,对吗? - RyanTimmons91
@Merlin 而不是反转它们(这在某些系统上可能是不正确的)- 我会简单地读取它们并使用“移位”操作...将其作为答案添加 - Marc Gravell
@Merlin33069:我建议您编辑您的问题以使其更清晰 - 我会在我的答案中提供一些选项。 - Jon Skeet
3个回答

4
string x = "abc";
byte[] data = Encoding.BigEndianUnicode.GetBytes(x);

在另一个方向上:

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

虽然它不是完全UCS-2,但对大多数情况来说已经足够了。

更新:Unicode FAQ

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

答:UCS-2是过时的术语,它指的是Unicode实现到Unicode 1.1之前,在版本2.0中添加代理代码点和UTF-16之前。现在应该避免使用这个术语。

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

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


更好地解释UCS-2 / UTF-16之间的区别...UTF-16 Unicode扩展A和B。UCS-2仅支持基本多文种平面(BMP)。 - J-16 SDiZ

2

UCS-2与UTF-16非常接近,使用Encoding.BigEndianUnicode几乎总是足够的。

关于读取长度前缀(作为大端字节序)的问题(注释),更正确的解决方法是通过移位操作来完成,在所有系统上都能正确执行。例如:

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

这样做将在任何系统上按照大端4字节整数解析方式工作,而不受本地字节序的影响。


2

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

  • 反转字节,然后使用内置的BitConverter代码(我假设你现在正在使用它或BinaryReader
  • 使用重复的“加法和移位”操作自己进行转换
  • 使用我的EndianBitConverterEndianBinaryReader类,来自MiscUtil,它们就像BitConverterBinaryReader,但让您指定字节序。

您可能正在寻找Encoding.BigEndianUnicode。这是大端UTF-16编码,严格来说并不与UCS-2相同(如Marc所指出的),但除非您提供包含BMP之外的字符的字符串(即U+FFFF以上),否则应该是可以的,因为这些字符不能在UCS-2中表示,但可以在UTF-16中表示。

来自Wikipedia页面

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

我发现客户端系统发送给您的字符中几乎不可能存在差异(这基本上就是替代对,它们已经永久保留用于此目的)。


或者在代理范围内。 - Ignacio Vazquez-Abrams
@Ignacio:我不确定你是在我的编辑之前还是之后发表了评论...你能再次检查一下,看看是否还有什么需要补充的吗? - Jon Skeet
据我所知,所有文本都应该是普通字符。 - RyanTimmons91
@Merlin33069:那我强烈怀疑问题不在你认为的地方。但是没有具体数据示例很难说。 - Jon Skeet
你在miscutils中的字节序转换器已经可用了,我希望我们能在最终项目中使用它。 - RyanTimmons91
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接