1290 Stimmen

Wie kann ich zufällige alphanumerische Zeichenfolgen erzeugen?

Wie kann ich eine zufällige 8 Zeichen alphanumerische Zeichenfolge in C# generieren?

2 Stimmen

Welcher Rest

8 Stimmen

O s o s

2 Stimmen

Es wäre schön, wenn die Sprachlokalisierung in diese Frage einbezogen würde. Vor allem, wenn Ihre Benutzeroberfläche für Chinesisch oder Bulgarisch geeignet sein soll!

43voto

CodesInChaos Punkte 103089

Die Hauptziele meines Codes sind:

  1. Die Verteilung der Strings ist nahezu gleichmäßig (geringe Abweichungen sind egal, solange sie klein sind)
  2. Es gibt mehr als ein paar Milliarden Zeichenfolgen für jedes Argument aus. Die Erzeugung einer Zeichenkette mit 8 Zeichen (~47 Bits Entropie) ist bedeutungslos, wenn Ihr PRNG nur 2 Milliarden (31 Bits Entropie) verschiedene Werte erzeugt.
  3. Es ist sicher, da ich davon ausgehe, dass die Leute es für Passwörter oder andere Sicherheitstoken verwenden werden.

Die erste Eigenschaft wird erreicht, indem ein 64-Bit-Wert modulo der Alphabetgröße genommen wird. Bei kleinen Alphabeten (wie den 62 Zeichen in der Frage) führt dies zu einer vernachlässigbaren Verzerrung. Die zweite und dritte Eigenschaft wird erreicht durch die Verwendung von RNGCryptoServiceProvider anstelle von System.Random .

using System;
using System.Security.Cryptography;

public static string GetRandomAlphanumericString(int length)
{
    const string alphanumericCharacters =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "abcdefghijklmnopqrstuvwxyz" +
        "0123456789";
    return GetRandomString(length, alphanumericCharacters);
}

public static string GetRandomString(int length, IEnumerable<char> characterSet)
{
    if (length < 0)
        throw new ArgumentException("length must not be negative", "length");
    if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody
        throw new ArgumentException("length is too big", "length");
    if (characterSet == null)
        throw new ArgumentNullException("characterSet");
    var characterArray = characterSet.Distinct().ToArray();
    if (characterArray.Length == 0)
        throw new ArgumentException("characterSet must not be empty", "characterSet");

    var bytes = new byte[length * 8];
    var result = new char[length];
    using (var cryptoProvider = new RNGCryptoServiceProvider())
    {
        cryptoProvider.GetBytes(bytes);
    }
    for (int i = 0; i < length; i++)
    {
        ulong value = BitConverter.ToUInt64(bytes, i * 8);
        result[i] = characterArray[value % (uint)characterArray.Length];
    }
    return new string(result);
}

38voto

nawfal Punkte 65966

Das Einfachste:

public static string GetRandomAlphaNumeric()
{
    return Path.GetRandomFileName().Replace(".", "").Substring(0, 8);
}

Sie können eine bessere Leistung erzielen, wenn Sie das Char-Array hart kodieren und sich auf System.Random :

public static string GetRandomAlphaNumeric()
{
    var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
    return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}

Wenn Sie befürchten, dass sich das englische Alphabet irgendwann ändern könnte und Sie dadurch Geschäftseinbußen erleiden könnten, dann können Sie auf Hardcoding verzichten, sollten aber etwas schlechtere Ergebnisse erzielen (vergleichbar mit Path.GetRandomFileName Ansatz)

public static string GetRandomAlphaNumeric()
{
    var chars = 'a'.To('z').Concat('0'.To('9')).ToList();
    return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}

public static IEnumerable<char> To(this char start, char end)
{
    if (end < start)
        throw new ArgumentOutOfRangeException("the end char should not be less than start char", innerException: null);
    return Enumerable.Range(start, end - start + 1).Select(i => (char)i);
}

Die letzten beiden Ansätze sehen besser aus, wenn Sie sie zu einer Erweiterungsmethode von System.Random Instanz.

24voto

drzaus Punkte 22843

Nur einige Leistungsvergleiche der verschiedenen Antworten in diesem Thread:

Methoden & Einrichtung

// what's available
public static string possibleChars = "abcdefghijklmnopqrstuvwxyz";
// optimized (?) what's available
public static char[] possibleCharsArray = possibleChars.ToCharArray();
// optimized (precalculated) count
public static int possibleCharsAvailable = possibleChars.Length;
// shared randomization thingy
public static Random random = new Random();

// http://stackoverflow.com/a/1344242/1037948
public string LinqIsTheNewBlack(int num) {
    return new string(
    Enumerable.Repeat(possibleCharsArray, num)
              .Select(s => s[random.Next(s.Length)])
              .ToArray());
}

// http://stackoverflow.com/a/1344258/1037948
public string ForLoop(int num) {
    var result = new char[num];
    while(num-- > 0) {
        result[num] = possibleCharsArray[random.Next(possibleCharsAvailable)];
    }
    return new string(result);
}

public string ForLoopNonOptimized(int num) {
    var result = new char[num];
    while(num-- > 0) {
        result[num] = possibleChars[random.Next(possibleChars.Length)];
    }
    return new string(result);
}

public string Repeat(int num) {
    return new string(new char[num].Select(o => possibleCharsArray[random.Next(possibleCharsAvailable)]).ToArray());
}

// http://stackoverflow.com/a/1518495/1037948
public string GenerateRandomString(int num) {
  var rBytes = new byte[num];
  random.NextBytes(rBytes);
  var rName = new char[num];
  while(num-- > 0)
    rName[num] = possibleCharsArray[rBytes[num] % possibleCharsAvailable];
  return new string(rName);
}

//SecureFastRandom - or SolidSwiftRandom
static string GenerateRandomString(int Length) //Configurable output string length
{
    byte[] rBytes = new byte[Length]; 
    char[] rName = new char[Length];
    SolidSwiftRandom.GetNextBytesWithMax(rBytes, biasZone);
    for (var i = 0; i < Length; i++)
    {
        rName[i] = charSet[rBytes[i] % charSet.Length];
    }
    return new string(rName);
}

Ergebnisse

Getestet in LinqPad. Für String-Größe von 10, erzeugt:

  • von Linq = chdgmevhcy [10]
  • von Loop = gtnoaryhxr [10]
  • from Select = rsndbztyby [10]
  • von GenerateRandomString = owyefjjakj [10]
  • von SecureFastRandom = VzougLYHYP [10]
  • von SecureFastRandom-NoCache = oVQXNGmO1S [10]

Und die Leistungszahlen schwanken gelegentlich leicht. NonOptimized ist tatsächlich schneller, und manchmal ForLoop y GenerateRandomString wechseln, wer die Führung hat.

  • LinqIsTheNewBlack (10000x) = 96762 Ticks verstrichen (9,6762 ms)
  • ForLoop (10000x) = 28970 Ticks verstrichen (2,897 ms)
  • ForLoopNonOptimized (10000x) = 33336 Ticks verstrichen (3,3336 ms)
  • Wiederholung (10000x) = 78547 Ticks verstrichen (7,8547 ms)
  • GenerateRandomString (10000x) = 27416 Ticks verstrichen (2,7416 ms)
  • SecureFastRandom (10000x) = 13176 verstrichene Ticks (5ms) niedrigste [anderer Rechner]
  • SecureFastRandom-NoCache (10000x) = 39541 Ticks verstrichen (17ms) niedrigste [anderer Rechner]

21voto

Pooran Punkte 1510

Eine Codezeile Membership.GeneratePassword() funktioniert das :)

Hier ist ein Demo für dasselbe.

15voto

Raj kumar Punkte 1105

Mein einfacher Ein-Zeilen-Code funktioniert bei mir :)

string  random = string.Join("", Guid.NewGuid().ToString("n").Take(8).Select(o => o));

Response.Write(random.ToUpper());
Response.Write(random.ToLower());

Um dies für eine beliebig lange Zeichenkette zu erweitern

    public static string RandomString(int length)
    {
        //length = length < 0 ? length * -1 : length;
        var str = "";

        do 
        {
            str += Guid.NewGuid().ToString().Replace("-", "");
        }

        while (length > str.Length);

        return str.Substring(0, length);
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X