我开发了一个随机字符串生成器,但它的行为并不像我希望的那样。我的目标是能够运行两次并生成两个不同的四个字符随机字符串。但是,它只生成一个四字符随机字符串两次。
以下是代码及其输出示例:
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;
......输出如下:UNTE-UNTE ......但它应该看起来像UNTE-FWNU
如何确保两个明显随机的字符串?
答案 0 :(得分:303)
您正在方法中创建Random实例,这会导致它在快速连续调用时返回相同的值。我会做这样的事情:
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;
(代码的修改版本)
答案 1 :(得分:185)
您正在实例化方法中的Random
对象。
Random
对象是seeded from the system clock,这意味着如果你快速连续多次调用你的方法,它每次都会使用相同的种子,这意味着它会生成相同的序列随机数字,这意味着你将获得相同的字符串。
要解决此问题,请将您的Random
实例移到方法本身之外(当您使用该方法时,您可以摆脱对Convert
和{{1}的疯狂调用序列}和Floor
):
NextDouble
答案 2 :(得分:134)
//一个非常简单的实现
using System.IO;
public static string RandomStr()
{
string rStr = Path.GetRandomFileName();
rStr = rStr.Replace(".", ""); // For Removing the .
return rStr;
}
//现在只需调用RandomStr()方法
答案 3 :(得分:49)
只要您使用的是Asp.Net 2.0或更高版本,您也可以使用库调用 -
System.Web.Security.Membership.GeneratePassword
,但它会包含特殊字符。
获得4个随机字符,最少0个特殊字符 -
Membership.GeneratePassword(4, 0)
答案 4 :(得分:20)
仅供一群人停下来,以及在一行代码中有一个随机字符串
int yourRandomStringLength = 12; //maximum: 32
Guid.NewGuid().ToString("N").Substring(0, yourRandomStringLength);
PS:请注意,yourRandomStringLength
不能超过32,因为Guid
的最大长度为32。
答案 5 :(得分:12)
另一个版本的字符串生成器。简单,没有花哨的数学和魔术数字。但是有一些魔术字符串指定允许的字符。
<强>更新强> 我使生成器静态,所以多次调用时它不会返回相同的字符串。但是,此代码不 线程安全,并且肯定不 加密安全。
对于密码生成,应使用System.Security.Cryptography.RNGCryptoServiceProvider
。
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();
}
答案 6 :(得分:12)
此解决方案是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);
}
}
答案 7 :(得分:10)
这是另一个选项:
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());
}
}
答案 8 :(得分:7)
最佳解决方案是将随机数生成器与base64转换一起使用
public string GenRandString(int length)
{
byte[] randBuffer = new byte[length];
RandomNumberGenerator.Create().GetBytes(randBuffer);
return System.Convert.ToBase64String(randBuffer).Remove(length);
}
答案 9 :(得分:4)
这是因为每个新的Random实例都会因为被调用这么快而生成相同的数字。 不要继续创建新实例,只需调用next()并在方法之外声明随机类。
答案 10 :(得分:4)
用于衡量标准的LINQ单行程(假设private static Random Random
)...
public static string RandomString(int length)
{
return new string(Enumerable.Range(0, length).Select(_ => (char)Random.Next('a', 'z')).ToArray());
}
答案 11 :(得分:3)
你应该在构造函数中启动一个类级别的Random对象,并在每次调用时重用(这将继续相同的伪随机数序列)。无参数构造函数已在内部使用Environment.TickCount为发生器设定种子。
答案 12 :(得分:2)
我添加了使用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);
}
}
答案 13 :(得分:2)
我想可能这也是可以接受和简单的。
Guid.NewGuid().ToString()
答案 14 :(得分:2)
以下是我对当前接受的答案的修改,我认为答案更快更短:
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();
}
注意我没有使用所有乘法,Math.floor()
,Convert
等。
编辑:random.Next(0x41, 0x5A)
可以更改为任何Unicode字符范围。
答案 15 :(得分:2)
我的RandomString()
方法生成随机字符串。
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);
}
答案 16 :(得分:1)
我创建了这个方法。
效果很好。
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;
}
答案 17 :(得分:1)
对于随机字符串生成器:
#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
答案 18 :(得分:1)
Here is a blog post为生成随机单词,句子和段落提供了更强大的类。
答案 19 :(得分:1)
实际上,一个好的解决方案是为随机数生成器提供一个静态方法,该方法是线程安全的,不使用锁。
这样,同时访问您的Web应用程序的多个用户不会获得相同的随机字符串。
这里有3个例子: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx
我会使用最后一个:
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();
}
}
然后你可以正确消除
Random random = new Random();
只需调用RandomGen3.Next(),您的方法就可以保持静态。
答案 20 :(得分:1)
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;
}
}
你也需要这个:
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;
}
}
而且:
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);
}
}
答案 21 :(得分:1)
如果您想为强密码生成一串数字和字符。
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();
}
答案 22 :(得分:1)
将“Pushcode”的答案与使用随机生成器的种子的答案相结合。我需要它来创建一系列伪可读的“单词”。
private int RandomNumber(int min, int max, int seed=0)
{
Random random = new Random((int)DateTime.Now.Ticks + seed);
return random.Next(min, max);
}
答案 23 :(得分:1)
这是基于GUID的另一个想法。我已将它用于Visual Studio performance test,以生成仅包含字母数字字符的随机字符串。
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);
}
答案 24 :(得分:0)
我发现这更有帮助,因为它是一个扩展,它允许您选择代码的来源。
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 };
希望这有帮助。
答案 25 :(得分:0)
在我的情况下,密码必须包含:
这是我的代码:
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;
}
答案 26 :(得分:0)
您好,您可以使用MMLib.RapidPrototyping nuget包中的WordGenerator或LoremIpsumGenerator。
using MMLib.RapidPrototyping.Generators;
public void WordGeneratorExample()
{
WordGenerator generator = new WordGenerator();
var randomWord = generator.Next();
Console.WriteLine(randomWord);
}
答案 27 :(得分:0)
如果您可以访问与英特尔安全密钥兼容的CPU,则可以使用以下库生成实际随机数和字符串:https://github.com/JebteK/RdRand和https://www.rdrand.com/
只需从here下载最新版本,包括Jebtek.RdRand并为其添加using语句。然后,您需要做的就是:
bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU
string key = RdRandom.GenerateKey(10); //Generate 10 random characters
另外,您还可以获得以下附加功能:
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
如果您没有兼容的CPU来执行代码,只需使用rdrand.com上的RESTful服务即可。使用项目中包含的RdRandom包装程序库,您只需要执行此操作(注册时可以获得1000个免费调用):
string ret = Randomizer.GenerateKey(<length>, "<key>");
您还可以按如下方式生成随机字节数组和无符号整数:
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
答案 28 :(得分:0)
而且,另一个版本:我在测试中使用这种方法生成随机伪股票代码:
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
用法:
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
您可以重新定义randChar函数,以便按位置而不是ascii代码使用“允许”字符数组:
char[] allowedchars = {'A','B','C','1','2','3'};
Func<char> randChar = () => allowedchars[rand.Next(0, allowedchars.Length-1)];
答案 29 :(得分:0)
另一个样本(在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);
由我自己实施。
答案 30 :(得分:0)
这是我的解决方案:
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;