6

我正在尝试在 .NET 中生成一个随机字符串并转换为字节,但遇到了一点困难。我想要完整的可能字符集,我的理解是字符串可以包含任何字符。

我的代码目前如下:

var plainText = new StringBuilder();
for (int j = 0; j < stringLength; ++j)
{
    plainText.Append((char)_random.Next(char.MinValue, char.MaxValue));
}
byte[] x = Encoding.Unicode.GetBytes(plainText.ToString());
string result = Encoding.Unicode.GetString(x);

理论上,plainText应该result是相同的。它们大多相同,但一些原始字符丢失了,似乎是 55000-57000 范围内的字符 - 它们被替换为字符 65533。

我假设问题出在我的编码上,但我认为 Unicode 可以正确处理这个问题。我尝试过 UTF8 和 UTF32,但它们给了我同样的问题。

有什么想法吗?

4

2 回答 2

9

问题是 0xD800-0xDFFF (55296-57343) 范围内的字符(称为 Unicode 代理字符)本身无效。它们必须成对出现(首先是 0xD800-0xDBFF,其次是 0xDC00-0xDFFF)才能有效(在 UTF-16 编码方案中)。单独,它们将被视为无效字符并解码为 0xFFFD (65533)。C# 使用 UTF-16 来表示其字符串,这就是您看到该输出的原因。

您可以选择将它们过滤掉(例如,调用_random.Next直到获得非代理字符),或者在生成代理字符时生成合法代理对。

于 2012-08-26T05:36:29.543 回答
2

这些是代理字符 55296-57343 (0xD800-0xDFFF)。您需要正确配对它们。UTF-16 中的一对代理字符描述了一个 unicode 代码点。

您似乎在假设 char 和 code-point 是同一事物的情况下进行操作。这不是真的,有 >2^16 个代码点。

我推荐阅读UTF-16 维基百科文章

于 2012-08-26T05:37:45.040 回答