Comment puis-je générer des chaînes alphanumériques aléatoires en C#? [fermé]

Comment puis-je générer des chaînes alphanumériques aléatoires de 8 caractères en C#?

737
demandé sur CodesInChaos 2009-08-28 03:07:24
la source

30 ответов

J'ai entendu dire que LINQ est le nouveau noir, donc voici ma tentative D'utiliser LINQ:

private static Random random = new Random();
public static string RandomString(int length)
{
    const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return new string(Enumerable.Repeat(chars, length)
      .Select(s => s[random.Next(s.Length)]).ToArray());
}

(Note: l'utilisation de la classe aléatoire rend ce Impropre à tout ce qui concerne la sécurité , comme la création de mots de passe ou de jetons. Utilisez la classe RNGCryptoServiceProvider si vous avez besoin d'un générateur de nombres aléatoires fort.)

1359
répondu dtb 2018-09-12 23:01:31
la source
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[8];
var random = new Random();

for (int i = 0; i < stringChars.Length; i++)
{
    stringChars[i] = chars[random.Next(chars.Length)];
}

var finalString = new String(stringChars);

pas aussi élégant que la solution Linq. (- :

(Note: l'utilisation de la classe aléatoire rend ce Impropre à tout ce qui concerne la sécurité , comme la création de mots de passe ou de jetons. Utilisez la classe RNGCryptoServiceProvider si vous avez besoin d'un générateur de nombres aléatoires fort.)

286
répondu Dan Rigby 2014-04-11 23:40:53
la source

cette implémentation (trouvée via google) me semble solide.

contrairement à certaines des alternatives présentées, celle-ci est cryptographique .

using System.Security.Cryptography;
using System.Text;

namespace UniqueKey
{
    public class KeyGenerator
    {
        public static string GetUniqueKey(int maxSize)
        {
            char[] chars = new char[62];
            chars =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
            byte[] data = new byte[1];
            using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
            {
                crypto.GetNonZeroBytes(data);
                data = new byte[maxSize];
                crypto.GetNonZeroBytes(data);
            }
            StringBuilder result = new StringBuilder(maxSize);
            foreach (byte b in data)
            {
                result.Append(chars[b % (chars.Length)]);
            }
            return result.ToString();
        }
    }
}

a choisi celui d'une discussion des alternatives ici

257
répondu Eric J. 2015-02-22 16:53:44
la source

Solution 1 - plus grande" gamme "avec la longueur la plus flexible

"
string get_unique_string(int string_length) {
    using(var rng = new RNGCryptoServiceProvider()) {
        var bit_count = (string_length * 6);
        var byte_count = ((bit_count + 7) / 8); // rounded up
        var bytes = new byte[byte_count];
        rng.GetBytes(bytes);
        return Convert.ToBase64String(bytes);
    }
}

Cette solution a plus de portée que l'utilisation d'une GUID parce qu'une GUID a un couple de bits fixes qui sont toujours les mêmes et donc pas au hasard, par exemple le 13 caractère dans hex est toujours" 4 " - au moins dans une version 6 GUID.

cette solution vous permet également de générer une chaîne de n'importe quelle longueur.

Solution 2 - Une ligne de code-bon pour jusqu'à 22 caractères

Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0, 8);

vous ne pouvez pas générer des chaînes aussi longtemps que Solution 1 et la chaîne n'a pas la même portée en raison de bits fixes dans les GUID, mais dans de nombreux cas, cela fera le travail.

Solution 3 - Un peu moins code

Guid.NewGuid().ToString("n").Substring(0, 8);

on garde ça ici pour des raisons historiques. Il utilise un peu moins le code, bien que vient comme la dépense d'avoir moins de gamme - parce qu'il utilise hex au lieu de base64 il faut plus de caractères pour représenter la même gamme par rapport aux autres solutions.

qui signifie plus de risque de collision - le tester avec 100.000 itérations de 8 chaînes de caractères généré un dupliqué.

166
répondu Douglas 2018-03-20 20:31:51
la source

voici un exemple que J'ai volé à Sam Allen exemple à Point Net Perls

si vous n'avez besoin que de 8 caractères, Utilisez Path.GetRandomFileName () dans le système.Io namespace. Sam dit d'utiliser le "chemin".La méthode GetRandomFileName ici est parfois supérieure, parce qu'elle utilise RNGCryptoServiceProvider pour une meilleure aléatoire. Cependant, il est limité à 11 caractères aléatoires."

GetRandomFileName retourne toujours un 12 caractères chaîne avec une période de 9 caractères. Donc, vous aurez besoin de supprimer la période (puisque ce n'est pas aléatoire) et puis de prendre 8 caractères de la chaîne. En fait, vous pouvez juste prendre les 8 premiers personnages et ne pas vous soucier de la période.

public string Get8CharacterRandomString()
{
    string path = Path.GetRandomFileName();
    path = path.Replace(".", ""); // Remove period.
    return path.Substring(0, 8);  // Return 8 character string
}

PS: thanks Sam

56
répondu Adam Porad 2009-08-28 03:37:43
la source

les principaux objectifs de mon code sont:

  1. la distribution des cordes est presque uniforme (ne vous souciez pas des déviations mineures, tant qu'elles sont petites)
  2. affiche plus de quelques milliards de chaînes pour chaque jeu d'arguments. Générer une chaîne de 8 caractères (~47 bits d'entropie) n'a pas de sens si votre PRNG ne génère que 2 milliards (31 bits d'entropie) de valeurs différentes.
  3. c'est sûr, car je m'attends à ce que les gens utilisez ceci pour les mots de passe ou autres clés de sécurité.

la première propriété est obtenue en prenant une valeur de 64 bits modulo la taille de l'alphabet. Pour les petits alphabets (tels que les 62 caractères de la question) cela conduit à un biais négligeable. La deuxième et la troisième propriété sont obtenues en utilisant RNGCryptoServiceProvider au lieu de 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];
    new RNGCryptoServiceProvider().GetBytes(bytes);
    var result = new char[length];
    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);
}
33
répondu CodesInChaos 2013-09-28 18:43:39
la source

le plus simple:

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

vous pouvez obtenir de meilleures performances si vous codez dur le tableau de char et de compter sur System.Random :

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

si jamais vous vous inquiétez les alphabets anglais peuvent changer autour et vous pourriez perdre des affaires, alors vous pouvez éviter le codage dur, mais devrait effectuer un peu pire (comparable à Path.GetRandomFileName approche)

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

les deux dernières approches semble mieux si vous pouvez faire une méthode d'extension sur l'instance System.Random .

29
répondu nawfal 2014-06-04 14:35:33
la source

Juste quelques comparaisons de performances des différentes réponses dans ce fil:

Méthodes D'Installation

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

résultats

testé dans LinqPad. Pour une taille de chaîne de 10, génère:

  • de Linq = chdgmevhcy [10]
  • de la Boucle = gtnoaryhxr [10]
  • de Select = rsndbztyby [10]
  • de GenerateRandomString = owyefjjakj [10]
  • de SecureFastRandom = VzougLYHYP [10]
  • de SecureFastRandom-NoCache = oVQXNGmO1S [10]

et les numéros de performance ont tendance à varier légèrement, très occasionnellement NonOptimized est en fait plus rapide, et parfois ForLoop et GenerateRandomString commutateur qui est en tête.

  • LinqIsTheNewBlack (10000x) = 96762 tiques écoulées (9,6762 ms)
  • ForLoop (10000x) = 28970 tiques écoulées (2,897 ms)
  • ForLoopNonOptimized (10000x) = 33336 tiques écoulées (3.3336 ms)
  • répéter (10000x) = 78547 tiques écoulées (7,8547 ms)
  • GenerateRandomString (10000x) = 27416 tiques écoulées (2,7416 ms)
  • SecureFastRandom (10000x) = 13176 tiques écoulées (5ms) la plus basse [machine différente]
  • SecureFastRandom-NoCache (10000x) = 39541 tiques écoulées (17ms) plus faible [machine différente]
18
répondu drzaus 2016-02-21 14:50:42
la source

Une seule ligne de code Membership.GeneratePassword() est le tour est joué :)

voici un demo pour le même.

16
répondu Pooran 2018-05-03 11:58:41
la source

le code écrit par Eric J. est assez bâclé (il est assez clair qu'il Date d'il y a 6 ans... il n'écrirait probablement pas ce code aujourd'hui), et il y a même des problèmes.

contrairement à certaines des alternatives présentées, celle-ci est cryptographiquement saine.

faux... Il y a un parti pris dans le mot de passe (comme écrit dans un commentaire), bcdefgh sont un peu plus probables que les autres (le a n'est pas parce que par le GetNonZeroBytes il n'est pas générer des octets avec une valeur de zéro, donc le biais pour le a est équilibré par cela), donc il n'est pas vraiment cryptographiquement sonore.

cela devrait corriger tous les problèmes.

public static string GetUniqueKey(int size = 6, string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new RNGCryptoServiceProvider())
    {
        var data = new byte[size];

        // If chars.Length isn't a power of 2 then there is a bias if
        // we simply use the modulus operator. The first characters of
        // chars will be more probable than the last ones.

        // buffer used if we encounter an unusable random byte. We will
        // regenerate it in this buffer
        byte[] smallBuffer = null;

        // Maximum random number that can be used without introducing a
        // bias
        int maxRandom = byte.MaxValue - ((byte.MaxValue + 1) % chars.Length);

        crypto.GetBytes(data);

        var result = new char[size];

        for (int i = 0; i < size; i++)
        {
            byte v = data[i];

            while (v > maxRandom)
            {
                if (smallBuffer == null)
                {
                    smallBuffer = new byte[1];
                }

                crypto.GetBytes(smallBuffer);
                v = smallBuffer[0];
            }

            result[i] = chars[v % chars.Length];
        }

        return new string(result);
    }
}
8
répondu xanatos 2015-08-12 10:53:36
la source

nous utilisons aussi des chaînes de caractères aléatoires personnalisées, mais nous avons implémenté comme helper de chaîne de caractères, ce qui nous donne une certaine flexibilité...

public static string Random(this string chars, int length = 8)
{
    var randomString = new StringBuilder();
    var random = new Random();

    for (int i = 0; i < length; i++)
        randomString.Append(chars[random.Next(chars.Length)]);

    return randomString.ToString();
}

Utilisation

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random();

ou

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16);
6
répondu Mr. Pumpkin 2014-06-26 19:12:32
la source

une autre option pourrait être D'utiliser Linq et de regrouper les barres aléatoires dans un stringbuilder.

var chars = "abcdefghijklmnopqrstuvwxyz123456789".ToArray();
string pw = Enumerable.Range(0, passwordLength)
                      .Aggregate(
                          new StringBuilder(),
                          (sb, n) => sb.Append((chars[random.Next(chars.Length)])),
                          sb => sb.ToString());
5
répondu AAD 2012-12-09 00:39:31
la source

Question: Pourquoi devrais-je perdre mon temps à utiliser Enumerable.Range au lieu de taper "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789" ?

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
    public static void Main()
    {
        var randomCharacters = GetRandomCharacters(8, true);
        Console.WriteLine(new string(randomCharacters.ToArray()));
    }

    private static List<char> getAvailableRandomCharacters(bool includeLowerCase)
    {
        var integers = Enumerable.Empty<int>();
        integers = integers.Concat(Enumerable.Range('A', 26));
        integers = integers.Concat(Enumerable.Range('0', 10));

        if ( includeLowerCase )
            integers = integers.Concat(Enumerable.Range('a', 26));

        return integers.Select(i => (char)i).ToList();
    }

    public static IEnumerable<char> GetRandomCharacters(int count, bool includeLowerCase)
    {
        var characters = getAvailableRandomCharacters(includeLowerCase);
        var random = new Random();
        var result = Enumerable.Range(0, count)
            .Select(_ => characters[random.Next(characters.Count)]);

        return result;
    }
}

réponse: les cordes magiques sont mauvaises. QUELQU'un a-t-il remarqué qu'il n'y avait pas de I dans ma corde en haut? Ma mère m'a appris à ne pas utiliser les cordes magiques pour cette raison...

N. B. 1: comme beaucoup d'autres comme @DTB l'ont dit, n'utilisez pas System.Random si vous besoin de sécurité cryptographique...

N. B. 2: Cette réponse n'est pas la plus efficace ou la plus courte, mais je voulais que l'espace sépare la réponse de la question. Le but de ma réponse est plus de mettre en garde contre les ficelles magiques que de fournir une réponse innovatrice et fantaisiste.

5
répondu Wai Ha Lee 2015-02-22 21:17:34
la source

Horrible, je sais, mais je ne pouvais pas m'en empêcher:


namespace ConsoleApplication2
{
    using System;
    using System.Text.RegularExpressions;

    class Program
    {
        static void Main(string[] args)
        {
            Random adomRng = new Random();
            string rndString = string.Empty;
            char c;

            for (int i = 0; i < 8; i++)
            {
                while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]"));
                rndString += c;
            }

            Console.WriteLine(rndString + Environment.NewLine);
        }
    }
}

4
répondu james 2009-08-28 04:37:59
la source

je cherchais une réponse plus spécifique, où je veux contrôler le format de la chaîne aléatoire et suis tombé sur ce post. Par exemple: les plaques d'immatriculation (des voitures) ont un format spécifique (par pays) et je voulais créer des plaques d'immatriculation aléatoires.

J'ai décidé d'écrire ma propre méthode d'extension de Hasard pour cette. (ceci est dans le but de réutiliser le même Objet aléatoire, comme vous pourriez avoir des doubles dans les scénarios multi-threading). J'ai créé un gist ( https://gist.github.com/SamVanhoutte/808845ca78b9c041e928 ), mais copiera aussi la classe extension ici:

void Main()
{
    Random rnd = new Random();
    rnd.GetString("1-###-000").Dump();
}

public static class RandomExtensions
{
    public static string GetString(this Random random, string format)
    {
        // Based on /q/how-can-i-generate-random-alphanumeric-strings-in-c-closed-30555/"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        return chars[random.Next(chars.Length)];
    }

    private static char getRandomNumeric(Random random)
    {
        string nums = "0123456789";
        return nums[random.Next(nums.Length)];
    }
}
4
répondu Sam Vanhoutte 2015-01-22 13:39:56
la source

une version légèrement plus propre de la solution de DTB.

    var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    var random = new Random();
    var list = Enumerable.Repeat(0, 8).Select(x=>chars[random.Next(chars.Length)]);
    return string.Join("", list);

vos préférences de style peuvent varier.

4
répondu Rob Deary 2015-04-27 23:47:05
la source

Mon simple ligne de code qui fonctionne pour moi :)

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

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

pour développer ceci pour n'importe quelle chaîne de longueur

    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);
    }
4
répondu Raj kumar 2018-04-05 14:12:58
la source

essayer de combiner deux parties: unique (séquence, compteur ou date ) et aléatoire

public class RandomStringGenerator
{
    public static string Gen()
    {
        return ConvertToBase(DateTime.UtcNow.ToFileTimeUtc()) + GenRandomStrings(5); //keep length fixed at least of one part
    }

    private static string GenRandomStrings(int strLen)
    {
        var result = string.Empty;

        var Gen = new RNGCryptoServiceProvider();
        var data = new byte[1];

        while (result.Length < strLen)
        {
            Gen.GetNonZeroBytes(data);
            int code = data[0];
            if (code > 48 && code < 57 || // 0-9
                code > 65 && code < 90 || // A-Z
                code > 97 && code < 122   // a-z
                )
            {
                result += Convert.ToChar(code);
            }
        }

        return result;
    }

    private static string ConvertToBase(long num, int nbase = 36)
    {
        var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //if you wish make algoritm more secure - change order of letter here

        // check if we can convert to another base
        if (nbase < 2 || nbase > chars.Length)
            return null;

        int r;
        var newNumber = string.Empty;

        // in r we have the offset of the char that was converted to the new base
        while (num >= nbase)
        {
            r = (int) (num % nbase);
            newNumber = chars[r] + newNumber;
            num = num / nbase;
        }
        // the last number to convert
        newNumber = chars[(int)num] + newNumber;

        return newNumber;
    }
}

Essais:

[Test]
    public void Generator_Should_BeUnigue1()
    {
        //Given
        var loop = Enumerable.Range(0, 1000);
        //When
        var str = loop.Select(x=> RandomStringGenerator.Gen());
        //Then
        var distinct = str.Distinct();
        Assert.AreEqual(loop.Count(),distinct.Count()); // Or Assert.IsTrue(distinct.Count() < 0.95 * loop.Count())
    }
3
répondu RouR 2015-06-15 10:51:51
la source
 public static string RandomString(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var random = new Random();
        return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
    }
3
répondu Tejas 2015-11-24 11:46:17
la source

après avoir examiné les autres réponses et les commentaires de CodeInChaos, ainsi que la réponse de CodeInChaos encore biaisée (bien que moins), j'ai pensé qu'une solution finale de coupe et de pâte était nécessaire. Alors, pendant que je mettais à jour ma réponse, j'ai décidé de faire un tour complet.

pour une version à jour de ce code, veuillez visiter le nouveau dépôt Hg sur Bitbucket: https://bitbucket.org/merarischroeder/secureswiftrandom . Je recommande vous copiez et collez le code de: https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default&fileviewer=file-view-default (assurez-vous que vous cliquez sur le bouton Raw pour le rendre plus facile à copier et assurez-vous que vous avez la dernière version, je pense que ce lien va à une version spécifique du code, pas la dernière).

mise à Jour des notes:

  1. concernant d'autres réponses - Si vous connaissez la longueur de la sortie, vous n'avez pas besoin d'un compilateur de chaîne, et en utilisant ToCharArray, cela crée et remplit le tableau (vous n'avez pas besoin de créer un tableau vide en premier)
  2. concernant d'autres réponses - vous devriez utiliser NextBytes, plutôt que d'obtenir un à la fois pour la performance
  3. techniquement, vous pouvez épingler le tableau octet pour un accès plus rapide.. cela vaut généralement la peine quand votre itération plus de 6-8 fois sur un tableau d'octets. (Non fait ici)
  4. l'Utilisation de RNGCryptoServiceProvider du meilleur de l'aléatoire
  5. l'Utilisation de la mise en cache de 1 mo de mémoire tampon de données aléatoires - l'analyse comparative montre en cache les octets vitesse d'accès est ~1000x plus rapide la prise de 9ms plus de 1 MO vs 989ms pour non mis en cache.
  6. rejet optimisé de la zone de biais dans ma nouvelle classe.

Fin de la solution à la question:

static char[] charSet =  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
static int byteSize = 256; //Labelling convenience
static int biasZone = byteSize - (byteSize % charSet.Length);
public string GenerateRandomString(int Length) //Configurable output string length
{
    byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible
    char[] rName = new char[Length];
    SecureFastRandom.GetNextBytesMax(rBytes, biasZone);
    for (var i = 0; i < Length; i++)
    {
        rName[i] = charSet[rBytes[i] % charSet.Length];
    }
    return new string(rName);
}

mais vous avez besoin de ma nouvelle classe (non testée):

/// <summary>
/// My benchmarking showed that for RNGCryptoServiceProvider:
/// 1. There is negligable benefit of sharing RNGCryptoServiceProvider object reference 
/// 2. Initial GetBytes takes 2ms, and an initial read of 1MB takes 3ms (starting to rise, but still negligable)
/// 2. Cached is ~1000x faster for single byte at a time - taking 9ms over 1MB vs 989ms for uncached
/// </summary>
class SecureFastRandom
{
    static byte[] byteCache = new byte[1000000]; //My benchmark showed that an initial read takes 2ms, and an initial read of this size takes 3ms (starting to raise)
    static int lastPosition = 0;
    static int remaining = 0;

    /// <summary>
    /// Static direct uncached access to the RNGCryptoServiceProvider GetBytes function
    /// </summary>
    /// <param name="buffer"></param>
    public static void DirectGetBytes(byte[] buffer)
    {
        using (var r = new RNGCryptoServiceProvider())
        {
            r.GetBytes(buffer);
        }
    }

    /// <summary>
    /// Main expected method to be called by user. Underlying random data is cached from RNGCryptoServiceProvider for best performance
    /// </summary>
    /// <param name="buffer"></param>
    public static void GetBytes(byte[] buffer)
    {
        if (buffer.Length > byteCache.Length)
        {
            DirectGetBytes(buffer);
            return;
        }

        lock (byteCache)
        {
            if (buffer.Length > remaining)
            {
                DirectGetBytes(byteCache);
                lastPosition = 0;
                remaining = byteCache.Length;
            }

            Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length);
            lastPosition += buffer.Length;
            remaining -= buffer.Length;
        }
    }

    /// <summary>
    /// Return a single byte from the cache of random data.
    /// </summary>
    /// <returns></returns>
    public static byte GetByte()
    {
        lock (byteCache)
        {
            return UnsafeGetByte();
        }
    }

    /// <summary>
    /// Shared with public GetByte and GetBytesWithMax, and not locked to reduce lock/unlocking in loops. Must be called within lock of byteCache.
    /// </summary>
    /// <returns></returns>
    static byte UnsafeGetByte()
    {
        if (1 > remaining)
        {
            DirectGetBytes(byteCache);
            lastPosition = 0;
            remaining = byteCache.Length;
        }

        lastPosition++;
        remaining--;
        return byteCache[lastPosition - 1];
    }

    /// <summary>
    /// Rejects bytes which are equal to or greater than max. This is useful for ensuring there is no bias when you are modulating with a non power of 2 number.
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="max"></param>
    public static void GetBytesWithMax(byte[] buffer, byte max)
    {
        if (buffer.Length > byteCache.Length / 2) //No point caching for larger sizes
        {
            DirectGetBytes(buffer);

            lock (byteCache)
            {
                UnsafeCheckBytesMax(buffer, max);
            }
        }
        else
        {
            lock (byteCache)
            {
                if (buffer.Length > remaining) //Recache if not enough remaining, discarding remaining - too much work to join two blocks
                    DirectGetBytes(byteCache);

                Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length);
                lastPosition += buffer.Length;
                remaining -= buffer.Length;

                UnsafeCheckBytesMax(buffer, max);
            }
        }
    }

    /// <summary>
    /// Checks buffer for bytes equal and above max. Must be called within lock of byteCache.
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="max"></param>
    static void UnsafeCheckBytesMax(byte[] buffer, byte max)
    {
        for (int i = 0; i < buffer.Length; i++)
        {
            while (buffer[i] >= max)
                buffer[i] = UnsafeGetByte(); //Replace all bytes which are equal or above max
        }
    }
}

Pour l'histoire - mon vieux solution pour répondre à cette question, utilisé Aléatoire de l'objet:

    private static char[] charSet =
      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();

    static rGen = new Random(); //Must share, because the clock seed only has Ticks (~10ms) resolution, yet lock has only 20-50ns delay.
    static int byteSize = 256; //Labelling convenience
    static int biasZone = byteSize - (byteSize % charSet.Length);
    static bool SlightlyMoreSecurityNeeded = true; //Configuration - needs to be true, if more security is desired and if charSet.Length is not divisible by 2^X.
    public string GenerateRandomString(int Length) //Configurable output string length
    {
      byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible
      char[] rName = new char[Length];
      lock (rGen) //~20-50ns
      {
          rGen.NextBytes(rBytes);

          for (int i = 0; i < Length; i++)
          {
              while (SlightlyMoreSecurityNeeded && rBytes[i] >= biasZone) //Secure against 1/5 increased bias of index[0-7] values against others. Note: Must exclude where it == biasZone (that is >=), otherwise there's still a bias on index 0.
                  rBytes[i] = rGen.NextByte();
              rName[i] = charSet[rBytes[i] % charSet.Length];
          }
      }
      return new string(rName);
    }

Performance:

  1. SecureFastRandom - premier passage = ~9-33ms . Imperceptible. en cours : 5ms (parfois jusqu'à 13ms) sur 10 000 itérations, avec une seule itération moyenne= 1,5 microsecondes. . Note: Nécessite généralement 2, mais de temps en temps jusqu'à 8 cache actualise - dépend du nombre d'octets dépasser le biais de la zone
  2. Aléatoire - Premier single run = ~0-1ms . Imperceptible. en cours : 5ms plus de 10 000 itérations. Avec une seule itération moyenne= .5 microsecondes. . Sur la même vitesse.
3
répondu Merari Schroeder 2016-02-20 15:48:00
la source

est maintenant dans une saveur à une doublure.

private string RandomName
    {
        get
        {
            return new string(
                Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                    .Select(s =>
                    {
                        var cryptoResult = new byte[4];
                        new RNGCryptoServiceProvider().GetBytes(cryptoResult);
                        return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                    })
                    .ToArray());
        }
    }
2
répondu Matas Vaitkevicius 2015-01-22 15:03:41
la source

une solution sans utiliser Random :

var chars = Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 8);

var randomStr = new string(chars.SelectMany(str => str)
                                .OrderBy(c => Guid.NewGuid())
                                .Take(8).ToArray());
2
répondu w.b 2015-08-11 13:02:05
la source

voici une variante de la solution D'Eric J, i.e. cryptographically sound, pour WinRT (Windows Store App):

public static string GenerateRandomString(int length)
{
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    var result = new StringBuilder(length);
    for (int i = 0; i < length; ++i)
    {
        result.Append(CryptographicBuffer.GenerateRandomNumber() % chars.Length);
    }
    return result.ToString();
}

si la performance est importante (surtout lorsque la longueur est élevée):

public static string GenerateRandomString(int length)
{
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    var result = new System.Text.StringBuilder(length);
    var bytes = CryptographicBuffer.GenerateRandom((uint)length * 4).ToArray();
    for (int i = 0; i < bytes.Length; i += 4)
    {
        result.Append(BitConverter.ToUInt32(bytes, i) % chars.Length);
    }
    return result.ToString();
}
2
répondu huyc 2015-10-27 17:20:20
la source

je sais que celui-ci n'est pas le meilleur moyen. Mais vous pouvez essayer ce.

string str = Path.GetRandomFileName(); //This method returns a random file name of 11 characters
str = str.Replace(".","");
Console.WriteLine("Random string: " + str);
1
répondu Sagar 2014-07-15 16:42:49
la source

Je ne sais pas comment cryptographiquement cela est, mais il est plus lisible et concis que les solutions plus complexes de loin (imo), et il devrait être plus" aléatoire "que" solutions basées sur 151920920".

return alphabet
    .OrderBy(c => Guid.NewGuid())
    .Take(strLength)
    .Aggregate(
        new StringBuilder(),
        (builder, c) => builder.Append(c))
    .ToString();

Je ne peux pas décider si je pense que cette version ou la suivante est "plus jolie", mais ils donnent exactement les mêmes résultats:

return new string(alphabet
    .OrderBy(o => Guid.NewGuid())
    .Take(strLength)
    .ToArray());

accordé, il n'est pas optimisé pour la vitesse, donc si sa mission critique pour générer des millions de des cordes aléatoires à chaque seconde, essayez-en une autre!

NOTE: Cette solution ne permet pas la répétition de symboles dans l'alphabet, et l'alphabet doit être de taille égale ou supérieure à la chaîne de sortie, ce qui rend cette approche moins souhaitable dans certaines circonstances, tout dépend de votre cas d'utilisation.

1
répondu sara 2016-01-14 21:14:30
la source

si vos valeurs ne sont pas complètement aléatoires, mais en fait peuvent dépendre de quelque chose - vous pouvez calculer un md5 ou sha1 hachage de ce "somwthing" et puis la tronquer à la longueur que vous voulez.

vous pouvez aussi générer et tronquer un guid.

0
répondu Alexey B. 2010-03-29 19:48:04
la source
public static class StringHelper
{
    private static readonly Random random = new Random();

    private const int randomSymbolsDefaultCount = 8;
    private const string availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    private static int randomSymbolsIndex = 0;

    public static string GetRandomSymbols()
    {
        return GetRandomSymbols(randomSymbolsDefaultCount);
    }

    public static string GetRandomSymbols(int count)
    {
        var index = randomSymbolsIndex;
        var result = new string(
            Enumerable.Repeat(availableChars, count)
                      .Select(s => {
                          index += random.Next(s.Length);
                          if (index >= s.Length)
                              index -= s.Length;
                          return s[index];
                      })
                      .ToArray());
        randomSymbolsIndex = index;
        return result;
    }
}
0
répondu KregHEk 2014-04-07 12:08:35
la source

voici un mécanisme pour générer une chaîne alphanumérique aléatoire (Je l'utilise pour générer des mots de passe et des données de test) sans définir l'alphabet et les nombres,

CleanupBase64 va supprimer les parties nécessaires dans la chaîne et continuer à ajouter des lettres alphanumériques aléatoires de façon récursive.

        public static string GenerateRandomString(int length)
        {
            var numArray = new byte[length];
            new RNGCryptoServiceProvider().GetBytes(numArray);
            return CleanUpBase64String(Convert.ToBase64String(numArray), length);
        }

        private static string CleanUpBase64String(string input, int maxLength)
        {
            input = input.Replace("-", "");
            input = input.Replace("=", "");
            input = input.Replace("/", "");
            input = input.Replace("+", "");
            input = input.Replace(" ", "");
            while (input.Length < maxLength)
                input = input + GenerateRandomString(maxLength);
            return input.Length <= maxLength ?
                input.ToUpper() : //In my case I want capital letters
                input.ToUpper().Substring(0, maxLength);
        }
0
répondu Dhanuka777 2015-09-30 05:55:02
la source

solution très simple. Il utilise des valeurs ASCII et génère simplement des caractères" aléatoires " entre les deux.

public static class UsernameTools
{
    public static string GenerateRandomUsername(int length = 10)
    {
        Random random = new Random();
        StringBuilder sbuilder = new StringBuilder();
        for (int x = 0; x < length; ++x)
        {
            sbuilder.Append((char)random.Next(33, 126));
        }
        return sbuilder.ToString();
    }

}
-1
répondu Serguei Fedorov 2015-06-22 01:46:18
la source

il suffit d'utiliser l'assemblage SRVTextToImage . Et écrivez le code ci-dessous pour générer une chaîne de caractères aléatoire.

CaptchaRandomImage c1 = new CaptchaRandomImage();
            string text = c1.GetRandomString(8);

la plupart du temps, il est utilisé pour mettre en œuvre le Captcha. Mais dans votre cas, il fonctionne également. Espérons que cela aide.

-3
répondu Salman Mushtaq 2016-02-16 22:05:59
la source

Autres questions sur c# .net random