【问题标题】:How to generate 8 characters, 900000 Upper alpha/numeric unique keys with C#?如何使用 C# 生成 8 个字符、900000 个大写字母/数字唯一键?
【发布时间】:2012-03-09 11:03:44
【问题描述】:

我正在尝试生成 900,000 个密钥并将它们存储到数据库中。

每个值必须是 8 个字符,并且与生成的字符不同。

这是我的代码,它运行良好,但速度太慢...

公共部分类 Form1 : Form
{
    公共表格1()
    {
        初始化组件();
    }

    私人无效按钮1_Click(对象发送者,EventArgs e)
    {
        richTextBox1.Visible = false;
        产生();
    }

    公共 int 数 = 0;

    私人无效 Den1()
    {
        for (int i = 0; i = 0)
            {
                MessageBox.Show("从 1 开始忽略重复!");
                一世 - ;
            }
            别的
            {
                richTextBox1.Text += randomStr + "\n";
                数++;
            }

            label1.Text = "" + 数字;
        }

        richTextBox1.Visible = true;
    }

    公共无效生成()
    {
        CheckForIllegalCrossThreadCalls = false;
        线程 thread1 = new Thread(Deneme1);

        thread1.Start();
    }

    私有字符串 RandomString(int 长度,字符串 allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
    {
        if (length (allowedChars).ToArray();
        if (byteSize 

【问题讨论】:

  • 你是在多核机器上运行代码吗?
  • 哪个数据库?我问这个是因为您可以直接使用 SQL 轻松地做到这一点。
  • 我使用的是 Intel Core i7 和 Sql 2008r2

标签: c# performance random


【解决方案1】:

首先,我会全部生成它们,然后然后将它们放入 UI。我也不会使用string.IndexOf 来查找您是否已经找到了匹配项。使用HashSet<string>:

HashSet<string> codes = new HashSet<string>();
while (codes.Count < 900000)
{
    codes.Add(RandomString(8));  
}
// Then do what you want with the codes

您也不应该CheckForIllegalCrossThreadCalls 设置为false。只需在后台生成它们,然后使用Invoke 进入 UI 线程以更新您的 UI。如果你真的想随时更新,你可以定期更新……虽然我不会把它们都放在一个文本框中。

接下来,我会看看RandomString 方法。你真的需要在每次迭代中创建一个新的RNGCryptoServiceProvider 吗?为什么不创建一个然后重复使用呢?

同样,为什么还要创建一个新的HashSet&lt;char&gt; 并在每次调用时调用ToArray?听起来您可能应该有一个单独的类作为 RandomCodeGenerator 记住:

  • 您生成的代码大小
  • 随机数生成器
  • 允许的字符

这将使您无需在每次迭代中进行大量设置工作。

然后我会亲自创建一个大小合适的char[],然后迭代直到填满它,然后从中创建一个字符串...我认为不需要StringBuilder...但这可能不会伤害你。

【讨论】:

  • 这种方法在数字大的情况下可能会很慢,因为每次哈希集实现找到重复项时,循环都会一次又一次地尝试。我宁愿用一系列值填充一个容器,然后随机选择每个元素并删除它。
  • 不错的一个:我不知道 HashSet 也允许您添加项已经存在的项目,本来会出现异常,但有道理
  • @vulkanino 但是它会比原始代码快得多,这可能已经足够好了+以后很容易理解
  • 有非常有用的建议。非常感谢。而对于您的 while 部分,它应该是“codes.Count
  • @LostInLib:不——直到你得到 900001 个代码才会停止。你只想要900000,对吧?
【解决方案2】:

您可以使用Guid 快速生成您的密钥:

Guid guid = Guid.NewGuid();

string theString = guid.ToString().Replace("-", string.Empty).Substring(0, 8).ToUpperInvariant();

【讨论】:

    【解决方案3】:

    您可以直接在 SQL 中执行此操作,例如:https://stackoverflow.com/a/9631898/403335

    但即使你用代码来做,我也会用所有可能值的序列填充一个容器。

    然后从序列容器中随机选择元素,使用该元素并将其从容器中删除。这样你一定会得到所有的号码,而不会浪费时间去寻找一个“空洞”号码(还没有被捡到)。

    在代码中:

        Random random = new Random();
        List<string> uniqueStrings = new List<string>(900000);
        List<string> randomString = new List<string>(900000);
    
        for (char c1 = 'A'; c1 <= 'Z'; ++c1) 
            for (char c2 = 'A'; c2 <= 'Z'; ++c2) 
                for (char c3 = 'A'; c3 <= 'Z'; ++c3) 
                    for (char c4 = 'A'; c4 <= 'Z'; ++c4) 
                        for (char c5 = 'A'; c5 <= 'Z'; ++c5) 
                            for (char c6 = 'A'; c6 <= 'Z'; ++c6) 
                                for (char c7 = 'A'; c7 <= 'Z'; ++c7) 
                                    for (char c8 = 'A'; c8 <= 'Z'; ++c8) 
                                        uniqueStrings.Add(string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", c1, c2, c3, c4, c5, c6, c7, c8));
    
        for (int i = 0; i < uniqueStrings.Count; i++)
        {
            const int index = random.Next(uniqueStrings.Count) + 1;
            randomString.Add(uniqueStrings[index]);
            uniqueStrings.RemoveAt(index);
        }
    

    【讨论】:

      【解决方案4】:

      首先,RichTextBox 不是一个合适的值存储。 TextBoxIndexOf 方法很可能是您的代码中最慢的部分,您需要将其替换为其他内容,我宁愿使用 HashSet&lt;string&gt; 来找出重复项。

      【讨论】:

        【解决方案5】:

        我认为这段代码可能会有所帮助

        public static string GeneratePassword()
        {
            string strPwdchar = "abcdefghijklmnopqrstuvwxyz0123456789#+@&$ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            string strPwd = "";
            Random rnd = new Random();
            for (int i = 0; i <= 7; i++)
            {
                int iRandom = rnd.Next(5, strPwdchar.Length - 1);
                strPwd += strPwdchar.Substring(iRandom, 1);
            }
            return strPwd;
        }
        

        在鼠标点击事件上迭代 90,000 次.....我希望一切正常

        【讨论】:

          【解决方案6】:

          看看这个讨论。
          我用于生成 +100.000 个唯一字符串的首选解决方案是 linked answer

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-17
            • 1970-01-01
            • 2021-01-12
            • 1970-01-01
            • 2016-05-09
            • 2015-07-29
            • 2018-10-01
            • 1970-01-01
            相关资源
            最近更新 更多