Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 生成对UTF-8编码和解码有效的随机字符串_C#_String_Random_Utf 8_Encode - Fatal编程技术网

C# 生成对UTF-8编码和解码有效的随机字符串

C# 生成对UTF-8编码和解码有效的随机字符串,c#,string,random,utf-8,encode,C#,String,Random,Utf 8,Encode,出于测试目的,我需要生成一个随机字符串,然后将其编码到字节数组中,以便通过Web传输并解码回结果字符串。测试使用NUnit框架将原始字符串与结果字符串进行比较。由于编码的字节数组必须对Web友好,因此使用UTF-8编码 字符串由Encoder.GetBytes从UTF8Encoding编码到字节数组中。字节数组由解码器解码为字符串。GetChars来自UTF8Encoding 原始字符串需要随机生成并包含任意字符序列,可以使用UTF-8编码对其进行编码/解码 我第一次尝试生成字符串是: p

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

字符串由
Encoder.GetBytes
UTF8Encoding
编码到字节数组中。字节数组由
解码器解码为字符串。GetChars
来自
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();
   }

我使用下面的代码生成随机的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();
}
private static readonly(int,int)[]头字节定义=
{

(1)我不认为随机字符串是单元测试的好方法,它从理论上打破了可重复的原则:测试每次都应该产生相同的结果。每次。测试不应该依赖于不可控的参数。我认为随机测试来自懒惰,为边缘情况创建实际测试。随机生成器是alw使用相同的密封值创建数组,因此每次测试运行时都会产生相同的结果,即测试是可重复的。如果它是有效的Unicode字符串,最好只使用U+0000和U+D7FF之间的值,因为U+E000上还有其他非法值。无论如何,您说“解码字节数组”。您能显示字节数组吗?在您的示例中只有UTF-16字符串。当然,U+FFFF以上的值对于任何Unicode测试都是必要的。如果只是随机噪声,则将每个字符创建为0到10FFFF之间的随机元素,并拒绝代理字符和非字符。列出了后者的所有66个。然后转换为UTF-8。不包括v高于0xE000的值有助于解决解码失败的问题。
   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);
   }
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();
}