Как сгенерировать 8 символов, 900000 верхних буквенно-цифровых уникальных ключей с C #? - PullRequest
1 голос
/ 09 марта 2012

Я пытаюсь сгенерировать 900 000 ключей и сохранить их в БД.

Каждое значение должно быть 8 символов и отличаться от сгенерированных.

Вот мой код выглядит, все хорошо, но слишком медленно ...

</p> <pre>public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { richTextBox1.Visible = false; Generate(); } public int num = 0; private void Den1() { for (int i = 0; i < 900000; i++) { string randomStr = RandomString(8); string textToSearchFor = randomStr; int index = richTextBox1.Text.IndexOf(textToSearchFor, StringComparison.OrdinalIgnoreCase); if (index >= 0) { MessageBox.Show("Duplicate ignored from 1!"); i--; } else { richTextBox1.Text += randomStr + "\n"; num++; } label1.Text = "" + num; } richTextBox1.Visible = true; } public void Generate() { CheckForIllegalCrossThreadCalls = false; Thread thread1 = new Thread(Deneme1); thread1.Start(); } private string RandomString(int length, string allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") { if (length < 0) throw new ArgumentOutOfRangeException("length", "length cannot be less than zero."); if (string.IsNullOrEmpty(allowedChars)) throw new ArgumentException("allowedChars may not be empty."); const int byteSize = 0x100; var allowedCharSet = new HashSet<char>(allowedChars).ToArray(); if (byteSize < allowedCharSet.Length) throw new ArgumentException(String.Format("allowedChars may contain no more than {0} characters.", byteSize)); // Guid.NewGuid and System.Random are not particularly random. By using a // cryptographically-secure random number generator, the caller is always // protected, regardless of use. using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider()) { var result = new StringBuilder(); var buf = new byte[128]; while (result.Length < length) { rng.GetBytes(buf); for (var i = 0; i < buf.Length && result.Length < length; ++i) { // Divide the byte into allowedCharSet-sized groups. If the // random value falls into the last group and the last group is // too small to choose from the entire allowedCharSet, ignore // the value in order to avoid biasing the result. var outOfRangeStart = byteSize - (byteSize % allowedCharSet.Length); if (outOfRangeStart <= buf[i]) continue; result.Append(allowedCharSet[buf[i] % allowedCharSet.Length]); } } return result.ToString(); } } }

Ответы [ 6 ]

4 голосов
/ 09 марта 2012

Ну, для начала я бы сгенерировал их все и затем поместил бы их в пользовательский интерфейс. Я также не стал бы использовать 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, чтобы перейти к потоку пользовательского интерфейса для обновления вашего пользовательского интерфейса. Если вы действительно хотите обновить по мере необходимости, вы можете делать это периодически ... хотя я бы не помещал их все в одно текстовое поле.

Далее я бы посмотрел на RandomString метод. Вам действительно нужно создавать новый RNGCryptoServiceProvider на каждой итерации? Почему бы не создать его, а затем использовать повторно?

Аналогично, зачем создавать новый HashSet<char> и звонить ToArray на каждый звонок ? Похоже, у вас должен быть отдельный класс RandomCodeGenerator, который помнит:

  • Размер кода, который вы генерируете
  • Генератор случайных чисел
  • Допустимые символы

Это позволит вам избавиться от большого количества работы по настройке на каждой итерации.

Я бы тогда лично создал char[] нужного размера и просто итерировал, пока вы его не заполнили, а затем создал бы строку из этого ... Я не вижу необходимости в StringBuilder ... но это, вероятно, не вредит тебе.

1 голос
/ 09 марта 2012

Вы можете сделать это непосредственно в 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);
    }
1 голос
/ 09 марта 2012

Вы можете использовать Guid для быстрой генерации ваших ключей:

Guid guid = Guid.NewGuid();

string theString = guid.ToString().Replace("-", string.Empty).Substring(0, 8).ToUpperInvariant();
0 голосов
/ 04 декабря 2016

Я думаю, этот код может быть полезен

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

Повторяйте это 90000 раз по событию щелчка мыши ..... Я надеюсь, что все будет работать

0 голосов
/ 09 марта 2012

Прежде всего RichTextBox не является подходящим хранилищем значений.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *.

0 голосов
/ 09 марта 2012

Посмотрите на это обсуждение.
Мое предпочтительное решение, которое я использую для генерации +100.000 уникальных строк, это связанный ответ

...