J'ai développé un générateur de chaîne aléatoire, mais il ne se comporte pas exactement comme je l'espère. Mon objectif est de pouvoir exécuter ceci deux fois et générer deux chaînes aléatoires distinctes de quatre caractères. Cependant, il génère simplement une chaîne aléatoire de quatre caractères deux fois.
Voici le code et un exemple de sa sortie:
private string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
Random random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
// get 1st random string
string Rand1 = RandomString(4);
// get 2nd random string
string Rand2 = RandomString(4);
// create full Rand string
string docNum = Rand1 + "-" + Rand2;
... et le résultat ressemble à ceci: UNTE-UNTE ... mais devrait ressembler à ceci: UNTE-FWNU
Comment puis-je assurer deux chaînes distinctement aléatoires?
Vous créez l'occurrence aléatoire dans la méthode, ce qui lui permet de renvoyer les mêmes valeurs lorsqu'il est appelé successivement. Je ferais quelque chose comme ça:
private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
private string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
// get 1st random string
string Rand1 = RandomString(4);
// get 2nd random string
string Rand2 = RandomString(4);
// creat full Rand string
string docNum = Rand1 + "-" + Rand2;
(version modifiée de votre code)
Vous instanciez l'objet Random
dans votre méthode.
L'objet Random
est issu de l'horloge système , ce qui signifie que si vous appelez votre méthode plusieurs fois à la suite, elle utilisera à chaque fois la même valeur d'origine, ce qui signifie générer la même séquence de nombres aléatoires, ce qui signifie que vous obtiendrez la même chaîne.
Pour résoudre le problème, déplacez votre instance Random
en dehors de la méthode elle-même (et tant que vous y serez, vous pourrez vous débarrasser de cette folle séquence d'appels à Convert
et Floor
et NextDouble
):
private readonly Random _rng = new Random();
private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string RandomString(int size)
{
char[] buffer = new char[size];
for (int i = 0; i < size; i++)
{
buffer[i] = _chars[_rng.Next(_chars.Length)];
}
return new string(buffer);
}
// Une implémentation très simple
using System.IO;
public static string RandomStr()
{
string rStr = Path.GetRandomFileName();
rStr = rStr.Replace(".", ""); // For Removing the .
return rStr;
}
// Maintenant, il suffit d'appeler RandomStr () Method
Tant que vous utilisez Asp.Net 2.0 ou une version ultérieure, vous pouvez également utiliser l'appel de la bibliothèque - System.Web.Security.Membership.GeneratePassword
, mais il comportera des caractères spéciaux.
Pour obtenir 4 caractères aléatoires avec un minimum de 0 caractères spéciaux-
_Membership.GeneratePassword(4, 0)
_
Juste pour les gens qui s'arrêtent et quoi d'avoir une chaîne aléatoire dans une seule ligne de code
int yourRandomStringLength = 12; //maximum: 32
Guid.NewGuid().ToString("N").Substring(0, yourRandomStringLength);
PS: Veuillez garder à l’esprit que yourRandomStringLength
ne peut pas dépasser 32 car Guid
a une longueur maximale de 32.
Cette solution est une extension pour une classe Random
.
class Program
{
private static Random random = new Random();
static void Main(string[] args)
{
random.NextString(10); // "cH*%I\fUWH0"
random.NextString(10); // "Cw&N%27+EM"
random.NextString(10); // "0LZ}nEJ}_-"
random.NextString(); // "kFmeget80LZ}nEJ}_-"
}
}
public static class RandomEx
{
/// <summary>
/// Generates random string of printable ASCII symbols of a given length
/// </summary>
/// <param name="r">instance of the Random class</param>
/// <param name="length">length of a random string</param>
/// <returns>Random string of a given length</returns>
public static string NextString(this Random r, int length)
{
var data = new byte[length];
for (int i = 0; i < data.Length; i++)
{
// All ASCII symbols: printable and non-printable
// data[i] = (byte)r.Next(0, 128);
// Only printable ASCII
data[i] = (byte)r.Next(32, 127);
}
var encoding = new ASCIIEncoding();
return encoding.GetString(data);
}
/// <summary>
/// Generates random string of printable ASCII symbols
/// with random length of 10 to 20 chars
/// </summary>
/// <param name="r">instance of the Random class</param>
/// <returns>Random string of a random length between 10 and 20 chars</returns>
public static string NextString(this Random r)
{
int length = r.Next(10, 21);
return NextString(r, length);
}
}
Encore une autre version du générateur de chaînes. Simple, sans mathématiques sophistiquées ni chiffres magiques. Mais avec une chaîne magique qui spécifie les caractères autorisés.
Mise à jour: J'ai créé un générateur statique, afin qu'il ne renvoie pas la même chaîne lorsqu'il est appelé plusieurs fois. Cependant ce code est pas thread-safe et est définitivement non cryptographiquement sécurisé .
Pour la génération de mot de passe System.Security.Cryptography.RNGCryptoServiceProvider
doit être utilisé.
_private Random _random = new Random(Environment.TickCount);
public string RandomString(int length)
{
string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; ++i)
builder.Append(chars[_random.Next(chars.Length)]);
return builder.ToString();
}
_
Voici une autre option:
public System.String GetRandomString(System.Int32 length)
{
System.Byte[] seedBuffer = new System.Byte[4];
using (var rngCryptoServiceProvider = new System.Security.Cryptography.RNGCryptoServiceProvider())
{
rngCryptoServiceProvider.GetBytes(seedBuffer);
System.String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
System.Random random = new System.Random(System.BitConverter.ToInt32(seedBuffer, 0));
return new System.String(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
}
}
La meilleure solution consiste à utiliser le générateur de nombres aléatoires avec la conversion base64
public string GenRandString(int length)
{
byte[] randBuffer = new byte[length];
RandomNumberGenerator.Create().GetBytes(randBuffer);
return System.Convert.ToBase64String(randBuffer).Remove(length);
}
Un LINQ one-liner pour faire bonne mesure (en supposant un private static Random Random
) ...
public static string RandomString(int length)
{
return new string(Enumerable.Range(0, length).Select(_ => (char)Random.Next('a', 'z')).ToArray());
}
Cela est dû au fait que chaque nouvelle instance de Random génère le même nombre d'appels appelés si rapidement. ne pas continuer à créer une nouvelle instance, appelez simplement next () et déclarez votre classe aléatoire en dehors de votre méthode.
Vous devez avoir un objet aléatoire de niveau classe initié une fois dans le constructeur et réutilisé à chaque appel (ceci continue la même séquence de nombres pseudo-aléatoires). Le constructeur sans paramètre ensemence déjà le générateur avec Environment.TickCount en interne.
J'ai ajouté l'option permettant de choisir la longueur à l'aide de la solution Ranvir
public static string GenerateRandomString(int length)
{
{
string randomString= string.Empty;
while (randomString.Length <= length)
{
randomString+= Path.GetRandomFileName();
randomString= randomString.Replace(".", string.Empty);
}
return randomString.Substring(0, length);
}
}
Ma méthode RandomString()
pour générer une chaîne aléatoire.
private static readonly Random _Rand = new Random();
/// <summary>
/// Generate a random string.
/// </summary>
/// <param name="length">The length of random string. The minimum length is 3.</param>
/// <returns>The random string.</returns>
public string RandomString(int length)
{
length = Math.Max(length, 3);
byte[] bytes = new byte[length];
_Rand.NextBytes(bytes);
return Convert.ToBase64String(bytes).Substring(0, length);
}
Je pense que c'est peut-être aussi acceptable et simple.
Guid.NewGuid().ToString()
Voici ma modification de la réponse actuellement acceptée, que je pense être un peu plus rapide et plus courte:
private static Random random = new Random();
private string RandomString(int size) {
StringBuilder builder = new StringBuilder(size);
for (int i = 0; i < size; i++)
builder.Append((char)random.Next(0x41, 0x5A));
return builder.ToString();
}
Notez que je n’ai pas utilisé toute la multiplication, Math.floor()
, Convert
etc.
EDIT: random.Next(0x41, 0x5A)
peut être modifié pour toute plage de caractères Unicode.
public static class StringHelpers
{
public static readonly Random rnd = new Random();
public static readonly string EnglishAlphabet = "abcdefghijklmnopqrstuvwxyz";
public static readonly string RussianAlphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
public static unsafe string GenerateRandomUTF8String(int length, string alphabet)
{
if (length <= 0)
return String.Empty;
if (string.IsNullOrWhiteSpace(alphabet))
throw new ArgumentNullException("alphabet");
byte[] randomBytes = rnd.NextBytes(length);
string s = new string(alphabet[0], length);
fixed (char* p = s)
{
for (int i = 0; i < s.Length; i++)
{
*(p + i) = alphabet[randomBytes[i] % alphabet.Length];
}
}
return s;
}
public static unsafe string GenerateRandomUTF8String(int length, params UnicodeCategory[] unicodeCategories)
{
if (length <= 0)
return String.Empty;
if (unicodeCategories == null)
throw new ArgumentNullException("unicodeCategories");
if (unicodeCategories.Length == 0)
return rnd.NextString(length);
byte[] randomBytes = rnd.NextBytes(length);
string s = randomBytes.ConvertToString();
fixed (char* p = s)
{
for (int i = 0; i < s.Length; i++)
{
while (!unicodeCategories.Contains(char.GetUnicodeCategory(*(p + i))))
*(p + i) += (char)*(p + i);
}
}
return s;
}
}
Vous aurez également besoin de ceci:
public static class RandomExtensions
{
public static string NextString(this Random rnd, int length)
{
if (length <= 0)
return String.Empty;
return rnd.NextBytes(length).ConvertToString();
}
public static byte[] NextBytes(this Random rnd, int length)
{
if (length <= 0)
return new byte[0];
byte[] randomBytes = new byte[length];
rnd.NextBytes(randomBytes);
return randomBytes;
}
}
Et ça:
public static class ByteArrayExtensions
{
public static string ConvertToString(this byte[] bytes)
{
if (bytes.Length <= 0)
return string.Empty;
char[] chars = new char[bytes.Length / sizeof(char)];
Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
}
Et voici une autre idée basée sur les GUID. Je l'ai utilisé pour le test de performance Visual Studio pour générer une chaîne aléatoire contenant uniquement des caractères alphanumériques.
public string GenerateRandomString(int stringLength)
{
Random rnd = new Random();
Guid guid;
String randomString = string.Empty;
int numberOfGuidsRequired = (int)Math.Ceiling((double)stringLength / 32d);
for (int i = 0; i < numberOfGuidsRequired; i++)
{
guid = Guid.NewGuid();
randomString += guid.ToString().Replace("-", "");
}
return randomString.Substring(0, stringLength);
}
En fait, une bonne solution consiste à utiliser une méthode statique pour le générateur de nombres aléatoires, qui est thread-safe et qui n’utilise pas de verrous.
De cette façon, plusieurs utilisateurs accédant à votre application Web en même temps ne reçoivent pas les mêmes chaînes aléatoires.
Il y a 3 exemples ici: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx
J'utiliserais le dernier:
public static class RandomGen3
{
private static RNGCryptoServiceProvider _global =
new RNGCryptoServiceProvider();
[ThreadStatic]
private static Random _local;
public static int Next()
{
Random inst = _local;
if (inst == null)
{
byte[] buffer = new byte[4];
_global.GetBytes(buffer);
_local = inst = new Random(
BitConverter.ToInt32(buffer, 0));
}
return inst.Next();
}
}
Ensuite, vous pouvez éliminer correctement
Random random = new Random();
Et appelez simplement RandomGen3.Next (), alors que votre méthode peut rester statique.
Si vous souhaitez générer une chaîne de chiffres et de caractères pour un mot de passe fort.
private static Random random = new Random();
private static string CreateTempPass(int size)
{
var pass = new StringBuilder();
for (var i=0; i < size; i++)
{
var binary = random.Next(0,2);
switch (binary)
{
case 0:
var ch = (Convert.ToChar(Convert.ToInt32(Math.Floor(26*random.NextDouble() + 65))));
pass.Append(ch);
break;
case 1:
var num = random.Next(1, 10);
pass.Append(num);
break;
}
}
return pass.ToString();
}
J'ai créé cette méthode.
Ça marche très bien.
public static string GeneratePassword(int Lenght, int NonAlphaNumericChars)
{
string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
Random rd = new Random();
if (NonAlphaNumericChars > Lenght || Lenght <= 0 || NonAlphaNumericChars < 0)
throw new ArgumentOutOfRangeException();
char[] pass = new char[Lenght];
int[] pos = new int[Lenght];
int i = 0, j = 0, temp = 0;
bool flag = false;
//Random the position values of the pos array for the string Pass
while (i < Lenght - 1)
{
j = 0;
flag = false;
temp = rd.Next(0, Lenght);
for (j = 0; j < Lenght; j++)
if (temp == pos[j])
{
flag = true;
j = Lenght;
}
if (!flag)
{
pos[i] = temp;
i++;
}
}
//Random the AlphaNumericChars
for (i = 0; i < Lenght - NonAlphaNumericChars; i++)
pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];
//Random the NonAlphaNumericChars
for (i = Lenght - NonAlphaNumericChars; i < Lenght; i++)
pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];
//Set the sorted array values by the pos array for the rigth posistion
char[] sorted = new char[Lenght];
for (i = 0; i < Lenght; i++)
sorted[i] = pass[pos[i]];
string Pass = new String(sorted);
return Pass;
}
Pour le générateur de chaîne aléatoire:
#region CREATE RANDOM STRING Word
char[] wrandom = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','W','Y','Z'};
Random random = new Random();
string random_string = "";
int count = 12; //YOU WILL SPECIFY HOW MANY CHARACTER WILL BE GENERATE
for (int i = 0; i < count; i++ )
{
random_string = random_string + wrandom[random.Next(0, 24)].ToString();
}
MessageBox.Show(random_string);
#endregion
Combinant la réponse par "Pushcode" et celle utilisant la graine pour le générateur aléatoire. J'en avais besoin pour créer une série de "mots" pseudo-lisibles.
private int RandomNumber(int min, int max, int seed=0)
{
Random random = new Random((int)DateTime.Now.Ticks + seed);
return random.Next(min, max);
}
Voici un article de blog qui fournit une classe un peu plus robuste pour générer des mots, des phrases et des paragraphes aléatoires.
Dans ma situation, le mot de passe doit contenir:
Voici mon code:
private string CreatePassword(int len)
{
string[] valid = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "1234567890", "!@#$%^&*()_+" };
RNGCryptoServiceProvider rndGen = new RNGCryptoServiceProvider();
byte[] random = new byte[len];
int[] selected = new int[len];
do
{
rndGen.GetNonZeroBytes(random);
for (int i = 0; i < random.Length; i++)
{
selected[i] = random[i] % 4;
}
}
while(selected.Distinct().Count() != 4);
rndGen.GetNonZeroBytes(random);
string res = "";
for(int i = 0; i<len; i++)
{
res += valid[selected[i]][random[i] % valid[selected[i]].Length];
}
return res;
}
Si vous avez accès à un processeur compatible Intel Secure Key, vous pouvez générer des nombres et des chaînes aléatoires réels à l'aide de ces bibliothèques: https://github.com/JebteK/RdRand et https://www.rdrand.com/
Il suffit de télécharger la dernière version de ici , d'inclure Jebtek.RdRand et d'ajouter une instruction using pour elle. Ensuite, tout ce que vous devez faire est la suivante:
bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU
string key = RdRandom.GenerateKey(10); //Generate 10 random characters
De plus, vous bénéficiez également de ces fonctionnalités supplémentaires:
string apiKey = RdRandom.GenerateAPIKey(); //Generate 64 random characters, useful for API keys
byte[] b = RdRandom.GenerateBytes(10); //Generate an array of 10 random bytes
uint i = RdRandom.GenerateUnsignedInt() //Generate a random unsigned int
Si vous n'avez pas de CPU compatible pour exécuter le code, utilisez simplement les services RESTful sur rdrand.com. Avec la bibliothèque de wrapper RdRandom incluse dans votre projet, il vous suffira de le faire (vous recevez 1000 appels gratuits lors de votre inscription):
string ret = Randomizer.GenerateKey(<length>, "<key>");
Vous pouvez également générer des tableaux d’octets aléatoires et des entiers non signés comme suit:
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Salut
vous pouvez utiliser WordGenerator ou LoremIpsumGenerator à partir du package de nuget MMLib.RapidPrototyping.
using MMLib.RapidPrototyping.Generators;
public void WordGeneratorExample()
{
WordGenerator generator = new WordGenerator();
var randomWord = generator.Next();
Console.WriteLine(randomWord);
}
J'ai trouvé cela plus utile, puisqu'il s'agit d'une extension et qu'il vous permet de sélectionner la source de votre code.
static string
numbers = "0123456789",
letters = "abcdefghijklmnopqrstvwxyz",
lettersUp = letters.ToUpper(),
codeAll = numbers + letters + lettersUp;
static Random m_Rand = new Random();
public static string GenerateCode(this int size)
{
return size.GenerateCode(CodeGeneratorType.All);
}
public static string GenerateCode(this int size, CodeGeneratorType type)
{
string source;
if (type == CodeGeneratorType.All)
{
source = codeAll;
}
else
{
StringBuilder sourceBuilder = new StringBuilder();
if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.Numbers)
sourceBuilder.Append(numbers);
if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.Letters)
sourceBuilder.Append(letters);
if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.LettersUpperCase)
sourceBuilder.Append(lettersUp);
source = sourceBuilder.ToString();
}
return size.GenerateCode(source);
}
public static string GenerateCode(this int size, string source)
{
StringBuilder code = new StringBuilder();
int maxIndex = source.Length-1;
for (int i = 0; i < size; i++)
{
code.Append(source[Convert.ToInt32(Math.Round(m_Rand.NextDouble() * maxIndex))]);
}
return code.ToString();
}
public enum CodeGeneratorType { Numbers = 1, Letters = 2, LettersUpperCase = 4, All = 16 };
J'espère que cela t'aides.
n autre échantillon (testé en vs2013):
Random R = new Random();
public static string GetRandomString(int Length)
{
char[] ArrRandomChar = new char[Length];
for (int i = 0; i < Length; i++)
ArrRandomChar[i] = (char)('a' + R.Next(0, 26));
return new string(ArrRandomChar);
}
string D = GetRandomString(12);
Mis en œuvre par moi-même.
Et une autre version: j’utilise cette méthode pour générer des pseudo-symboles aléatoires dans des tests:
Random Rand = new Random();
Func<char> randChar = () => (char)Rand.Next(65, 91); // upper case ascii codes
Func<int,string> randStr = null;
randStr = (x) => (x>0) ? randStr(--x)+randChar() : ""; // recursive
Usage:
string str4 = randStr(4);// generates a random 4 char string
string strx = randStr(Rand.next(1,5)); // random string between 1-4 chars in length
Vous pouvez redéfinir la fonction randChar à utiliser avec un tableau de caractères "autorisé" par position au lieu de code ascii:
char[] allowedchars = {'A','B','C','1','2','3'};
Func<char> randChar = () => allowedchars[Rand.Next(0, allowedchars.Length-1)];
Ceci est ma solution:
private string RandomString(int length)
{
char[] symbols = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
Stack<byte> bytes = new Stack<byte>();
string output = string.Empty;
for (int i = 0; i < length; i++)
{
if (bytes.Count == 0)
{
bytes = new Stack<byte>(Guid.NewGuid().ToByteArray());
}
byte pop = bytes.Pop();
output += symbols[(int)pop % symbols.Length];
}
return output;
}
// get 1st random string
string Rand1 = RandomString(4);
// get 2nd random string
string Rand2 = RandomString(4);
// create full Rand string
string docNum = Rand1 + "-" + Rand2;