生成随机字符串

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);

在理论上,plainTextresult 应该是相同的。它们大多数情况下是相同的,但是一些原始字符丢失了,似乎是在55000-57000范围内的字符 - 它们被替换为字符65533。
我假设问题出在我的编码上,但我认为Unicode会正确处理这个问题。我已经尝试过UTF8和UTF32,但是这些都给我带来了同样的问题。
有什么想法吗?

奇怪?!Unicode 可能会出现问题,但是当你用 UTF-32 进行测试时呢?! - TheHe
1
你想要实现什么目标? - CodesInChaos
我猜你正在生成一个包含无配对代理字符的无效UTF-16字符串。 - CodesInChaos
@CodesInChaos 我正在编写一个加密库的测试,通过生成一个随机的Unicode字符串,对其进行加密、解密,并确保输入和输出完全相同。 - Joe Enos
2
加密库通常操作字节或字节块,因此仅生成随机字节数组可能更值得。 - nneonneo
@nneonneo 感谢您。这个加密库确实可以专门处理字节数组,但我提供了一种重载方法来加密字符串,首先将它们转换为字节数组,然后使用用户选择的任何编码来加密字节数组。这就是我测试随机Unicode字符串的原因,因此我可以确保这些重载方法适用于Unicode字符串。 - Joe Enos
2个回答

11
问题在于范围为0xD800-0xDFFF(55296-57343)的字符,称为Unicode代理字符,在其自身上不是有效的。它们必须以一对出现(先是0xD800-0xDBFF,后是0xDC00-0xDFFF),才能有效(在UTF-16编码方案中)。孤立存在时,它们将被视为无效字符,并解码为0xFFFD(65533)。C#使用UTF-16表示其字符串,这就是为什么您看到该输出的原因。
您可以选择过滤掉它们(例如调用_random.Next直到获得非代理字符),或者每次生成代理字符时生成合法的代理对。

太棒了,谢谢。我以前没有处理过代理字符。 - Joe Enos

3

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

您似乎认为char和代码点是相同的东西。这不是真的,有超过2^16个代码点。

我建议阅读UTF-16维基百科文章


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