我如何在c#中生成一个随机的8个字符的字母数字字符串?


当前回答

不使用Random的解决方案:

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

var randomStr = new string(chars.SelectMany(str => str)
                                .OrderBy(c => Guid.NewGuid())
                                .Take(8).ToArray());

其他回答

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

不如Linq解决方案优雅。

(注意:Random类的使用使得它不适用于任何与安全性相关的事情,比如创建密码或令牌。如果你需要强随机数生成器,请使用RNGCryptoServiceProvider类。)

只需一行代码member . generatepassword()就可以做到这一点。

这里有一个相同的演示。

问:为什么我要浪费时间使用Enumerable ?范围,而不是输入“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;
    }
}

答案:魔术弦不好。有没有人注意到在我的字符串顶部没有“I”?我妈妈教我不要用魔法弦就是因为这个原因……

注意事项1:正如许多像@dtb这样的人所说,不要使用系统。随机的,如果你需要密码安全…

注2:这个答案不是最有效或最短的,但我想用空间把答案和问题分开。我回答这个问题的目的,更多的是为了警告人们不要使用神奇的字符串,而不是提供一个花哨的创新答案。

在这个线程中只是一些不同答案的性能比较:

方法与设置

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

结果

在LinqPad中测试。对于长度为10的字符串,生成:

from Linq = chdgmevhcy [10] from Loop = gtnoaryhxr [10] from Select = rsndbztyby [10] from GenerateRandomString = owyefjjakj [10] from securefastrrandom = VzougLYHYP [10] from securefastrrandom - nocache = oVQXNGmO1S [10]

性能数据会有细微的变化,偶尔NonOptimized会更快,有时ForLoop和GenerateRandomString会切换谁领先。

LinqIsTheNewBlack (10000x) = 96762 ticks elapsed (9.6762 ms) ForLoop (10000x) = 28970滴答流逝(2.897毫秒) ForLoopNonOptimized (10000x) = 33336滴答流逝(3.3336毫秒) 重复(10000x) = 78547滴答流逝(7.8547毫秒) GenerateRandomString (10000x) = 27416 tick elapsed (2.7416 ms) securefastrrandom (10000x) = 13176滴答流逝(5ms)最低[不同的机器] securefastrrandom - nocache (10000x) = 39541 ticks elapsed (17ms) low[不同的机器]

我的代码的主要目标是:

弦的分布几乎是均匀的(不关心微小的偏差,只要它们很小) 它为每个参数集输出超过几十亿个字符串。如果您的PRNG只生成20亿(31位熵)不同的值,那么生成8个字符的字符串(约47位熵)是没有意义的。 它是安全的,因为我希望人们使用它作为密码或其他安全令牌。

第一个属性是通过对字母大小取一个64位值的模来实现的。对于小字母(例如问题中的62个字符),这导致了可以忽略不计的偏差。第二个和第三个属性是通过使用RNGCryptoServiceProvider而不是System.Random来实现的。

using System;
using System.Security.Cryptography;

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

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

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