Gerador de Cadeia Aleatória Retornando a Mesma Cadeia

Eu desenvolvi um gerador random de strings, mas ele não está se comportando como eu espero. Meu objective é poder executar isso duas vezes e gerar duas strings aleatórias distintas de quatro caracteres. No entanto, apenas gera uma string aleatória de quatro caracteres duas vezes.

Aqui está o código e um exemplo de sua saída:

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; 

… e a saída é assim: UNTE-UNTE … mas deve ser algo como isto UNTE-FWNU

Como posso garantir duas strings distintamente aleatórias?

Você está fazendo a instância Random no método, o que faz com que ele retorne os mesmos valores quando chamado em sucessão rápida. Eu faria algo assim:

 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; 

(versão modificada do seu código)

Você está instanciando o object Random dentro do seu método.

O object Random é propagado do relógio do sistema , o que significa que se você chamar seu método várias vezes em uma rápida sucessão, ele usará a mesma semente a cada vez, o que significa que ele gerará a mesma sequência de números randoms, o que significa que você vai pegar a mesma corda.

Para resolver o problema, mova sua instância Random fora do método em si (e enquanto estiver nisso, você poderá se livrar dessa sequência louca de chamadas para Convert e Floor e 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); } 

// Uma implementação muito simples

 using System.IO; public static string RandomStr() { string rStr = Path.GetRandomFileName(); rStr = rStr.Replace(".", ""); // For Removing the . return rStr; } 

// Agora é só chamar o método RandomStr ()

Contanto que você esteja usando o Asp.Net 2.0 ou superior, você também pode usar a biblioteca chamada System.Web.Security.Membership.GeneratePassword , no entanto includeá caracteres especiais.

Para obter 4 caracteres randoms com um mínimo de 0 caracteres especiais –

 Membership.GeneratePassword(4, 0) 

Apenas para as pessoas passando e o que ter uma string aleatória em apenas uma linha de código

 int yourRandomStringLength = 12; //maximum: 32 Guid.NewGuid().ToString("N").Substring(0, yourRandomStringLength); 

PS: Lembre-se de que yourRandomStringLength não pode exceder 32, pois o Guid tem o tamanho máximo de 32.

Ainda outra versão do gerador de string. Simples, sem matemática extravagante e dígitos mágicos. Mas com alguma string mágica que especifica caracteres permitidos.

Atualização: Tornei o gerador estático, para que ele não retorne a mesma string quando chamado várias vezes. No entanto, esse código não é thread-safe e definitivamente não é criptograficamente seguro .

Para geração de senha, System.Security.Cryptography.RNGCryptoServiceProvider deve ser usado.

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

Essa solução é uma extensão para uma class Random .

Uso

 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}_-" } } 

Implementação

 public static class RandomEx { ///  /// Generates random string of printable ASCII symbols of a given length ///  /// instance of the Random class /// length of a random string /// Random string of a given length 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); } ///  /// Generates random string of printable ASCII symbols /// with random length of 10 to 20 chars ///  /// instance of the Random class /// Random string of a random length between 10 and 20 chars public static string NextString(this Random r) { int length = r.Next(10, 21); return NextString(r, length); } } 

Aqui está mais uma opção:

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

A melhor solução é usar o gerador de números randoms junto com a conversão base64

 public string GenRandString(int length) { byte[] randBuffer = new byte[length]; RandomNumberGenerator.Create().GetBytes(randBuffer); return System.Convert.ToBase64String(randBuffer).Remove(length); } 

Isso ocorre porque cada nova instância de Random está gerando os mesmos números de serem chamados tão rapidamente. Não continue criando uma nova instância, apenas chame next () e declare sua class aleatória fora de seu método.

Um one-liner LINQ para uma boa medida (assumindo um private static Random Random ) …

 public static string RandomString(int length) { return new string(Enumerable.Range(0, length).Select(_ => (char)Random.Next('a', 'z')).ToArray()); } 

Você deve ter um object Random de nível de class iniciado uma vez no construtor e reutilizado em cada chamada (isso continua a mesma sequência de números pseudo-randoms). O construtor sem parâmetros já semeia o gerador com Environment.TickCount internamente.

Eu adicionei a opção de escolher o comprimento usando a solução 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); } } 

Aqui está minha modificação da resposta aceita atualmente, que acredito ser um pouco mais rápida e curta:

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

Repare que eu não usei toda a multiplicação, Math.floor() , Convert etc.

EDIT: random.Next(0x41, 0x5A) pode ser alterado para qualquer intervalo de caracteres Unicode.

Meu método RandomString() para gerar uma string aleatória.

 private static readonly Random _rand = new Random(); ///  /// Generate a random string. ///  /// The length of random string. The minimum length is 3. /// The random string. 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); } 

Eu acho que pode ser isso também é aceitável e simples.

 Guid.NewGuid().ToString() 

Se você quisesse gerar uma string de números e caracteres para uma senha forte.

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

Combinando a resposta por “Pushcode” e aquele usando a semente para o gerador random. Eu precisava criar uma série de “palavras” pseudo-legíveis.

 private int RandomNumber(int min, int max, int seed=0) { Random random = new Random((int)DateTime.Now.Ticks + seed); return random.Next(min, max); } 

Eu criei esse método.

Isso funciona muito bem.

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

E aqui está outra ideia baseada em GUIDs. Eu usei para o teste de desempenho do Visual Studio para gerar seqüência aleatória contendo apenas caracteres alfanuméricos.

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

Aqui está uma postagem no blog que fornece uma class um pouco mais robusta para gerar palavras, frases e parágrafos randoms.

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

Você também precisará disso:

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

E isto:

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

Na verdade, uma boa solução é ter um método estático para o gerador de números randoms que seja thread-safe e não use bloqueios.

Dessa forma, vários usuários que acessam seu aplicativo da Web ao mesmo tempo não recebem as mesmas strings aleatórias.

Existem 3 exemplos aqui: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

Eu usaria o último:

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

Então você pode eliminar corretamente

 Random random = new Random(); 

E apenas chame RandomGen3.Next (), enquanto seu método pode permanecer estático.

Para gerador de string random:

 #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 

Eu achei isso mais útil, já que é uma extensão, e permite que você selecione a origem do seu código.

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

Espero que isto ajude.

Na minha situação, a senha deve conter:

  • Pelo menos uma minúscula.
  • Pelo menos uma maiúscula.
  • Pelo menos um decimal.
  • Pelo menos um caractere especial.

Aqui está o meu código:

  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 

Olá
você pode usar o WordGenerator ou LoremIpsumGenerator do pacote nuget MMLib.RapidPrototyping.

 using MMLib.RapidPrototyping.Generators; public void WordGeneratorExample() { WordGenerator generator = new WordGenerator(); var randomWord = generator.Next(); Console.WriteLine(randomWord); } 

Site Nuget
Site do projeto Codeplex

Se você tiver access a uma CPU compatível com Intel Secure Key, poderá gerar números e strings randoms reais usando essas bibliotecas: https://github.com/JebteK/RdRand e https://www.rdrand.com/

Apenas baixe a versão mais recente daqui , inclua Jebtek.RdRand e adicione uma instrução using para ele. Então, tudo que você precisa fazer é isto:

 bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU string key = RdRandom.GenerateKey(10); //Generate 10 random characters 

Além disso, você também obtém esses resources adicionais:

 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 

Se você não tiver uma CPU compatível para executar o código, basta usar os serviços RESTful em rdrand.com. Com a biblioteca de wrapper RdRandom incluída no seu projeto, você só precisa fazer isso (você recebe 1000 chamadas gratuitas quando se inscreve):

 string ret = Randomizer.GenerateKey(, ""); 

Você também pode gerar matrizes de bytes randoms e inteiros sem sinal da seguinte maneira:

 uint ret = Randomizer.GenerateUInt(""); byte[] ret = Randomizer.GenerateBytes(, ""); 

Outra amostra (testada no 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); 

Implementado por mim mesmo.

Esta é minha solução:

 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 bytes = new Stack(); string output = string.Empty; for (int i = 0; i < length; i++) { if (bytes.Count == 0) { bytes = new Stack(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;