在字符串中定义4字节UTF-16字符

7
我阅读了关于UTF-8、UTF-16和UCS-2的问题(链接),几乎所有答案都认为UCS-2已经过时,而C#使用UTF-16。
然而,我尝试在C#中创建4字节字符U+1D11E的所有尝试都失败了,因此我认为C#仅使用UTF-16的UCS-2子集。
以下是我的尝试:
string s = "\u1D11E"; // gives the 2 character string "ᴑE", because \u1D11 is ᴑ
string s = (char) 0x1D11E; // won't compile because of an overflow
string s = Encoding.Unicode.GetString(new byte[] {0xD8, 0x34, 0xDD, 0x1E}); // gives 㓘ờ

C#字符串真的是UTF-16,还是实际上是UCS-2?如果它们是UTF-16,我该如何将小提琴谱号插入我的C#字符串中?

1
最简单的方法就是在源代码中包含该字符,即 string s = "";。我建议您使用UTF-8编码保存您的.cs文件。这个位于补充多语言平面中的字符将占用UTF-8中的四个八位字节。当存储在内存中时,它将占用两个UTF-16代码单元或char值,也称为代理对。 - Jeppe Stig Nielsen
是的,我在维基百科上读到了相关内容,这就是为什么我尝试使用 Encoding.GetString() 方法的原因。 - Thomas Weller
3个回答

16

请使用大写字母 U:

  string s = "\U0001D11E";

您忽略了大多数机器都是小端序的:

  string t = Encoding.Unicode.GetString(new byte[] { 0x34, 0xD8, 0x1E, 0xDD });

我非常喜欢你在逐字节编码中找到了我的错误。虽然其他答案也找到了大写U的解决方案,但这就是我接受你的答案的原因。 - Thomas Weller
1
但是,除非您的 .cs 源代码文件保存在一些 1 字节的 "ANSI" 代码页中,否则您应该考虑简单地执行 string s = "";。这非常自然。 - Jeppe Stig Nielsen

5

C#绝对使用UTF-16编码。定义范围在U+0000 - U+FFFF以外的字符的正确方式是使用转义序列,允许使用8个十六进制数字来定义字符:

string s = "\U0001D11E";

如果您使用\u1D11E,它将被解释为U+1D11字符后跟一个E

当使用这些字符时需要记住的一件事是String.Length属性和大多数字符串方法适用于UTF-16代码单元,而不是Unicode字符。从MSDN文档中可以看到:

Length属性返回此实例中Char对象的数量,而不是Unicode字符的数量。原因是Unicode字符可能由多个Char表示。使用System.Globalization.StringInfo类来处理每个Unicode字符,而不是每个Char。


+1 因为我不知道 StringInfo。但是,上面的两个变体在屏幕上也显示为 2 个字符。 - Thomas Weller
你使用什么来在屏幕上显示字符串? - Joni
我尝试使用WinForms和一个标签以及一个文本框,使用默认字体(可能是Arial)。 - Thomas Weller
应该可以了。不过我发现另一个问题,请看更新。 - Joni

2
根据C#规范,长度超过4个十六进制字符的字符使用\U(大写U)和8个十六进制字符进行编码。一旦在字符串中正确编码,它就可以使用任何Unicode编码正确导出。
string s = "\U0001D11E";

foreach (var b in Encoding.UTF32.GetBytes(s))
    Console.WriteLine(b.ToString("x2"));

Console.WriteLine();

foreach (var b in Encoding.Unicode.GetBytes(s))
    Console.WriteLine(b.ToString("x2"));

> 1e
> d1
> 01
> 00
>
> 34
> d8
> 1e
> dd

你的例子使用UTF-32获取字节。我要求使用UTF-16。 - Thomas Weller
@ThomasW。我刚刚使用UTF32以清晰的方式展示了4字节字符如何使用\U正确编码到字符串中。UTF-16是一种小于4字节每个字符的多字节编码,使得字节的十六进制转储与原始值之间的联系不够清晰。 - Joachim Isaksson
@ThomasW。添加了一个UTF-16的示例。 - Joachim Isaksson

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