3

出于测试目的,我需要生成一个随机字符串,然后将其编码为字节数组以通过 Web 传输并解码回结果字符串。该测试使用 NUnit 框架将原始字符串与结果字符串进行比较。由于编码后的字节数组必须对 Web 友好,因此使用 UTF-8 编码。

字符串由Encoder.GetBytesfrom编码为字节数组UTF8Encoding。字节数组由Decoder.GetCharsfrom解码为字符串UTF8Encoding

原始字符串需要随机生成,包含任意字符序列,可以使用 UTF-8 编码进行编码/解码。

我第一次尝试生成字符串是:

   public static String RandomString(Random rnd, Int32 length) {
          StringBuilder str = new StringBuilder(length);
          for (int i = 0; i < length; i++)
                 str.Append((char)rnd.Next(char.MinValue, char.MaxValue));
          return str.ToString();
   }

上面的代码会生成带有无效序列的字符串进行编码。

我在网上找到了一些建议并改进了代码:

   public static String RandomString(Random rnd, Int32 length) {
          StringBuilder str = new StringBuilder(length);
          for (int i = 0; i < length; i++) {
                 char c = (char)rnd.Next(char.MinValue, char.MaxValue);
                 while (c >= 0xD800 && c <= 0xDFFF)
                        c = (char)rnd.Next(char.MinValue, char.MaxValue);
                 str.Append(c);
          return str.ToString();
   }

上面的代码编码没有问题,但是解码字节数组失败。此外,我不确定代码是否可以涵盖所有可能的情况。

任何建议,如何在 C# 中生成具有给定要求的随机字符串。

UPD:在编码/解码中使用随机字符串:

   public static Encoder Utf8Encode = new UTF8Encoding(false, true).GetEncoder();
   public static Decoder Utf8Decode = new UTF8Encoding(false, true).GetDecoder();

   public unsafe void TestString(Random rnd, int length, byte* byteArray, 
                 int arrayLenght) {
          int encodedLen;
          String str = RandomString(rnd, length);
          fixed (char* pStr = str) {
                 encodedLen = Utf8Encode.GetBytes(pStr, str.Length, byteArray,
                        arrayLenght, true);
          }
          char* buffer = stackalloc char[8192];
          int decodedLen = Utf8Decode.GetChars(byteArray, encodedLen, buffer, 
                 8192, true);
          String res = new String(buffer, 0, decodedLen);
          Assert.AreEqual(str, res);
   }
4

1 回答 1

0

我使用下面的代码生成随机 UTF-8 字符字节序列。我不能保证它捕获了 UTF-8 规范的各个方面,但它对我的测试目的很有价值,所以我把它贴在这里。

private static readonly (int, int)[] HeadByteDefinitions =
{
    (1 << 7, 0b0000_0000),
    (1 << 5, 0b1100_0000),
    (1 << 4, 0b1110_0000),
    (1 << 3, 0b1111_0000)
};

static byte[] RandomUtf8Char(Random gen)
{
    const int totalNumberOfUtf8Chars = (1 << 7) + (1 << 11) + (1 << 16) + (1 << 21);
    int tailByteCnt;
    var rnd = gen.Next(totalNumberOfUtf8Chars);
    if (rnd < (1 << 7))
        tailByteCnt = 0;
    else if (rnd < (1 << 7) + (1 << 11))
        tailByteCnt = 1;
    else if (rnd < (1 << 7) + (1 << 11) + (1 << 16))
        tailByteCnt = 2;
    else
        tailByteCnt = 3;

    var (range, offset) = HeadByteDefinitions[tailByteCnt];
    var headByte = Convert.ToByte(gen.Next(range) + offset);
    var tailBytes = Enumerable.Range(0, tailByteCnt)
        .Select(_ => Convert.ToByte(gen.Next(1 << 6) + 0b1000_0000));

    return new[] {headByte}.Concat(tailBytes).ToArray();
}
于 2021-03-01T10:24:58.247 回答