吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 473|回复: 9
收起左侧

[经验求助] c# 如何更高效率的随机一个位数较长的字符串

[复制链接]
夜雨闻笛 发表于 2024-7-7 07:46
25吾爱币
大佬们好,小白又来问小白问题了,新手写代码天天都是问题,只能厚着脸皮来求大佬指教,希望大佬们能帮帮忙祝大佬们生活顺心,薪水年年暴涨。

问题:取较长长度的随机字符串,一种是数字字符串,一种是字母字符串。我自己现在用的代码如下:






求助原因:感觉运行有点慢。
以10万次为例:字母字符串(生成长度为10)超过1200毫秒,如果是大小混合时间更是会翻倍。数字字符串会快一些,但也有270毫秒左右。
要求:用C#语言,尽可能高效率的优化。
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
string 取随机数字字符串(){
    string 返回字符串 = "";
    for (int i = 0; i < 2; i++)
    {
        int a = 取随机整数(0, int.MaxValue);
        if (a >= 1000000000)
        {
            返回字符串 += a.ToString();
        }
        else
        {
            返回字符串 += a.ToString().PadLeft(10, '0');
        }
    }
    return 返回字符串;
}
 
string 取随机x个字母(int 要几个字母, byte 大写填1小写填2混合填3)
{
    string 返回字符串 = "";
    int 随机数;
    char 字符;
    if (大写填1小写填2混合填3 == 1)
    {
        for (int j = 0; j < 要几个字母; j++)
        {
            随机数 = 取随机整数(65, 91);
            字符 = (char)随机数;
            返回字符串 += 字符;
        }
    }
    else if (大写填1小写填2混合填3 == 2)
    {
        for (int j = 0; j < 要几个字母; j++)
        {
            随机数 = 取随机整数(97, 123);//小写范围97~122
            while (随机数 == 108) //永远不会取到不好辨认的L小写字母,l编码108
            {
                随机数 = 取随机整数(97, 123);
            }
            字符 = (char)随机数;
            返回字符串 += 字符;
        }
    }
    else
    {
        for (int j = 0; j < 要几个字母; j++)
        {
            if (取随机整数(1, 3) == 1)
            {
                随机数 = 取随机整数(65, 91);
            }
            else
            {
                随机数 = 取随机整数(97, 123);
            }
            while (随机数 == 73 || 随机数 == 108)//如果是混合大小写,那么I和L都不能随机到   因为大写I和小写L很容易弄混
            {
                if (取随机整数(1, 3) == 1)
                {
                    随机数 = 取随机整数(65, 91);
                }
                else
                {
                    随机数 = 取随机整数(97, 123);
                }
            }
            字符 = (char)随机数;
            返回字符串 += 字符;
        }
    }
 
    return 返回字符串;
}
 
int 取随机整数(int 最小值, int 最大值)
{
    byte[] b = Guid.NewGuid().ToByteArray();
    int b1 = BitConverter.ToInt32(b, 0);
    Random ran = new(b1);
    return ran.Next(最小值, 最大值);
}



不知道有没有精研效率秘法的精锐大佬出手帮忙优化一下?

最佳答案

查看完整内容

32位字符……没有运行测试,供您参考: [mw_shl_code=csharp,true]using System; using System.Security.Cryptography; using System.Runtime.CompilerServices; public static class PasswordGenerator { private static readonly RNGCryptoServiceProvider SharedRng = new RNGCryptoServiceProvider(); private const string CharSet = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()-_=+ ...

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

shuisanyue 发表于 2024-7-7 07:46
32位字符……没有运行测试,供您参考:


[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Security.Cryptography;
using System.Runtime.CompilerServices;
public static class PasswordGenerator
{
    private static readonly RNGCryptoServiceProvider SharedRng = new RNGCryptoServiceProvider();
    private const string CharSet = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()-_=+[]{}|;:,.<>?";
    private const int CharSetSize = CharSet.Length;
    public static string GenStr(int length)
    {
        var result = new char[length];
        Span<byte> bytes = stackalloc byte[length * 4];
        SharedRng.GetBytes(bytes);
        for (int i = 0, j = 0; i < length; i++, j += 4)
        {
            uint randomIndex = (uint)(bytes[j] << 24 | bytes[j + 1] << 16 | bytes[j + 2] << 8 | bytes[j + 3]);
            result[i] = CharSet[randomIndex % CharSetSize];
        }
        return new string(result);
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static uint GetRandomUInt32(Span<byte> bytes, ref int index)
    {
        return (uint)(bytes[index] << 24 | bytes[index + 1] << 16 | bytes[index + 2] << 8 | bytes[index + 3]);
    }
}
class Program
{
    static void Main()
    {
        string password = PasswordGenerator.GenStr(32);
        Console.WriteLine(password);
    }
}
zazakgfh 发表于 2024-7-7 12:06
这个中文变量名给我整笑了
现在这个都不手动撸代码了
直接调用别人的一个库,一个叫随机密码的库
shuisanyue 发表于 2024-7-7 13:13
没有测试,看看时间开销多少?

[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using System.Text;
 
public class RandUtil
{
    private static readonly Random rnd = new Random();
 
    public static string GrtRndNumStr(int count)
    {
        StringBuilder sb = new StringBuilder((count * 11) / 2);
        byte[] buffer = new byte[4 * count];
        rnd.NextBytes(buffer);
 
        for (int i = 0; i < buffer.Length; i += 4)
        {
            uint num = BitConverter.ToUInt32(buffer, i);
            num %= 10000000000;
            sb.Append(num.ToString());
            if ((i / 4 + 1) % 2 == 0 && i < buffer.Length - 4) sb.Append(',');
        }
 
        return sb.ToString();
    }
 
    public static string GrtRndCharStr(int count, int typ)
    {
        StringBuilder sb = new StringBuilder(count);
        byte[] buffer = new byte[count];
        rnd.NextBytes(buffer);
 
        foreach (byte b in buffer)
        {
            char ch = (char)(typ == 1 ? b + 'A' : b + 'a');
            if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') sb.Append(ch);
        }
 
        return sb.ToString();
    }
}
 楼主| 夜雨闻笛 发表于 2024-7-7 16:16
zazakgfh 发表于 2024-7-7 12:06
这个中文变量名给我整笑了
现在这个都不手动撸代码了
直接调用别人的一个库,一个叫随机密码的库

哈哈,大佬别嫌辣眼睛,不会英语,要是用英文单词变量名方法名,那就连自己写的代码自己都看不懂了。
 楼主| 夜雨闻笛 发表于 2024-7-7 17:11
shuisanyue 发表于 2024-7-7 13:13
没有测试,看看时间开销多少?

[mw_shl_code=csharp,true]using System;

大佬,你的代码我测试了一下,效率比我的高多了。无论哪一种的十万次都能跑30毫秒左右。
但是有一个问题是字符串随机生成位数不正确。
在GrtRndCharStr的foreach里面,有一句if是只有char满足范围时才会被StringBuilder 添加,而不满足则跳过了。这会使得返回结果和指定长度不符合。
我想用while解决(不知道合不合适),而且关键代码也不会写:
public static string 取指定长度大写字母字符串(int count)
{
    StringBuilder sb = new(count);
    byte[] buffer = new byte[count];
    rnd.NextBytes(buffer);

    for (int i = 0; i < buffer.Length; i++)
    {
        char ch = (char)(buffer + 'A');
        while (ch < 'A' || ch > 'Z')
        {
            //如果ch不在大写字母范围,就重新生成ch
            //如何重新随机这个值不会写,未完成
        }
        sb.Append(ch);
    }

    return sb.ToString();
}
flyer_2001 发表于 2024-7-7 19:10
夜雨闻笛 发表于 2024-7-7 17:11
大佬,你的代码我测试了一下,效率比我的高多了。无论哪一种的十万次都能跑30毫秒左右。
但是有一个问题 ...

把大写字母加入到一个列表或数组中,随机生成序号,不需要的字母不要加
 楼主| 夜雨闻笛 发表于 2024-7-7 20:13
zazakgfh 发表于 2024-7-7 12:06
这个中文变量名给我整笑了
现在这个都不手动撸代码了
直接调用别人的一个库,一个叫随机密码的库

之前都没注意到最后一句话,原来有现成的库吗?
大佬,我在项目程序包和百度都搜了一下随机密码库 ,不知道具体是哪个库,能告诉我一下这个库的全名吗?
shuisanyue 发表于 2024-7-7 22:26
RNGCryptoServiceProvider看看这个,没有测试,参考一下:

[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Security.Cryptography;
public class PassGen
{
    private const string Upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private const string Lower = Upper.ToLower();
    private const string Nums = "0123456789";
    private const string Specs = "!@#$%^&*()-_=+[]{}|;:,.<>?";
    public static string GenPass(int len)
    {
        var charSet = Upper + Lower + Nums + Specs;
        var passChars = new char[len];
        var rng = new RNGCryptoServiceProvider();
        byte[] buf = new byte[4];
        for (int i = 0; i < passChars.Length; i++)
        {
            rng.GetBytes(buf);
            uint rand = BitConverter.ToUInt32(buf, 0);
            passChars[i] = charSet[rand % charSet.Length];
        }
        return new string(passChars);
    }
}
 
class Prog
{
    static void Main()
    {
        string pass = PassGen.GenPass(30);
        Console.WriteLine(pass);
    }
}
shuisanyue 发表于 2024-7-7 22:30
本帖最后由 shuisanyue 于 2024-7-7 22:31 编辑

上面不能改了……
RNGCryptoServiceProvider看看这个,没有测试,供您参考一下(2):


[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
using System.Security.Cryptography;
using System.Text;
public class PassGen
{
    private static readonly RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    private const string Upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private const string Lower = Upper.ToLower();
    private const string Nums = "0123456789";
    private const string Specs = "!@#$%^&*()-_=+[]{}|;:,.<>?";
    private static readonly string CharSet = new StringBuilder(Upper)
        .Append(Lower)
        .Append(Nums)
        .Append(Specs)
        .ToString();
    public static string GenPass(int len)
    {
        char[] passChars = new char[len];
        byte[] buf = new byte[4];
        for (int i = 0; i < len; i += 4)
        {
            rng.GetBytes(buf);
            uint rand = BitConverter.ToUInt32(buf, 0);
            for (int j = i; j < Math.Min(i + 4, len); j++)
            {
                passChars[j] = CharSet[rand % CharSet.Length];
                rand /= CharSet.Length;
            }
        }
        return new string(passChars);
    }
}
 
class Prog
{
    static void Main()
    {
        string pass = PassGen.GenPass(30);
        Console.WriteLine(pass);
    }
}
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-7-7 10:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表