如何生成随机字母数字字符串?

时间:2009-08-27 23:07:25

标签: c# .net random

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

33 个答案:

答案 0 :(得分:1484)

我听说LINQ是新的黑色,所以这是我尝试使用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());
}

(注意:使用Random类会使不适合任何与安全相关的内容,例如创建密码或令牌。如果使用RNGCryptoServiceProvider类,请使用{{1}}类。你需要一个强大的随机数发生器。)

答案 1 :(得分:327)

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类,请使用{{1}}类。你需要一个强大的随机数发生器。)

答案 2 :(得分:293)

这个实现(通过谷歌找到)看起来很合理。

与提供的某些替代方案不同,此方案加密声音

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

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

从讨论替代方案here

中挑选出一个

答案 3 :(得分:184)

解决方案1 ​​ - 具有最灵活长度的最大“范围”

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

此解决方案比使用GUID具有更多范围,因为GUID具有一些始终相同的固定位,因此不是随机的,例如十六进制中的13个字符始终为“4” - 至少在版本6中GUID。

此解决方案还允许您生成任意长度的字符串。

解决方案2 - 一行代码 - 最多22个字符

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

只要 Solution 1 ,就不能生成字符串,并且由于GUID中的固定位,字符串不具有相同的范围,但在很多情况下,这将完成工作。

解决方案3 - 代码略少

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

主要是为了历史目的而保留这里。它使用稍微少一点的代码,虽然这是为了减少范围 - 因为它使用十六进制而不是base64,与其他解决方案相比,它需要更多的字符来表示相同的范围。

这意味着更多的碰撞机会 - 使用100,000个8个字符串的迭代测试它会产生一个重复。

答案 4 :(得分:59)

这是我从Dot Net Perls

的Sam Allen案例中偷走的一个例子

如果只需要8个字符,则在System.IO命名空间中使用Path.GetRandomFileName()。 Sam说使用“Path.GetRandomFileName方法有时候更好,因为它使用RNGCryptoServiceProvider来获得更好的随机性。但是,它只限于11个随机字符。”

GetRandomFileName始终返回一个12个字符的字符串,其句点为第9个字符。所以你需要去除句点(因为那不是随机的)然后从字符串中取出8个字符。实际上,你可以只取前8个字符而不用担心这个时期。

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

PS:谢谢Sam

答案 5 :(得分:35)

我的代码的主要目标是:

  1. 字符串的分布几乎是均匀的(只要它们很小就不关心微小的偏差)
  2. 它为每个参数集输出超过几十亿个字符串。如果你的PRNG只产生20亿(31位熵)不同的值,那么生成一个8个字符的字符串(约47位的熵)是没有意义的。
  3. 这是安全的,因为我希望人们将其用于密码或其他安全令牌。
  4. 第一个属性是通过取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);
    }
    

答案 6 :(得分:29)

最简单的:

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

如果您对char数组进行硬编码并依赖System.Random

,则可以获得更好的性能
public static string GetRandomAlphaNumeric()
{
    var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
    return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}

如果您担心英语字母可能会在某个时间发生变化而您可能会失去业务,那么您可以避免使用硬编码,但应该执行稍差(与Path.GetRandomFileName方法相比)

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

如果您可以在System.Random实例上将它们作为扩展方法,则最后两种方法看起来会更好。

答案 7 :(得分:20)

对这个帖子中的各种答案进行一些性能比较:

方法&amp;设置

// 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,生成:

  
      
  • 来自Linq = chdgmevhcy [10]
  •   
  • 来自Loop = gtnoaryhxr [10]
  •   来自Select = rsndbztyby [10] 的
  •   
  • 来自GenerateRandomString = owyefjjakj [10]
  •   
  • 来自SecureFastRandom = VzougLYHYP [10]
  •   
  • 来自SecureFastRandom-NoCache = oVQXNGmO1S [10]
  •   

性能数字往往略有不同,偶尔NonOptimized实际上更快,有时ForLoopGenerateRandomString会改变谁的领先地位。

  
      
  • LinqIsTheNewBlack(10000x)= 96762个刻度(9.6762毫秒)
  •   
  • ForLoop(10000x)=经过28970个刻度(2.897毫秒)
  •   
  • ForLoopNonOptimized(10000x)= 33336个刻度已过去(3.3336毫秒)
  •   
  • 重复(10000x)=经过78547个刻度(7.8547毫秒)
  •   
  • GenerateRandomString(10000x)=经过27416个刻度(2.7416毫秒)
  •   
  • SecureFastRandom(10000x)= 13176个刻度(5ms)最低[不同的机器]
  •   
  • SecureFastRandom-NoCache(10000x)= 39541个经过时间(17毫秒)最低[不同机器]
  •   

答案 8 :(得分:17)

一行代码Membership.GeneratePassword()可以解决问题:)

这是一个demo

答案 9 :(得分:10)

Eric J.编写的代码非常草率(很明显它是从6年前开始的......他今天可能不会编写代码),甚至还有一些问题。

  

与所提供的一些替代方案不同,这个方案在密码方面是合理的。

不真实......密码存在偏差(如评论中所述),bcdefgh比其他人更可能(a不是因为{GetNonZeroBytes 1}}它不生成值为零的字节,因此a的偏差由它平衡),因此它不是真正的加密声音。

这应该可以解决所有问题。

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

答案 10 :(得分:6)

另一种选择可能是使用Linq并将随机字符聚合到字符串构建器中。

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

答案 11 :(得分:6)

我简单的一行代码对我有用:)

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

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

为任何长度的字符串扩展此

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

答案 12 :(得分:6)

我们也使用自定义字符串随机,但我们实现了作为字符串的助手,因此它提供了一些灵活性......

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

用法

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random();

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16);

答案 13 :(得分:6)

问题:为什么我要浪费时间使用Enumerable.Range而不是输入"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”?我妈妈教我不要因为这个原因而使用魔法弦......

n.b。 1:正如许多其他像@dtb所说的那样,如果你需要加密安全性,请不要使用System.Random ......

n.b。 2:这个答案不是最有效或最短的,但我希望空间能够将答案与问题分开。我的回答的目的更多是警告魔法字符串,而不是提供一个奇特的创新答案。

答案 14 :(得分:5)

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

您的风格偏好可能会有所不同。

答案 15 :(得分:4)

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

答案 16 :(得分:4)

在审核了其他答案并考虑CodeInChaos的评论后,CodeInChaos仍然偏向(虽然较少)答案,我认为需要最终的终极剪切和粘贴解决方案。因此,在更新我的答案时,我决定全力以赴。

有关此代码的最新版本,请访问Bitbucket上的新Hg存储库:https://bitbucket.org/merarischroeder/secureswiftrandom。我建议您复制并粘贴以下代码:https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default&fileviewer=file-view-default(确保单击“原始”按钮以便更容易复制并确保您拥有最新版本,我认为此链接转到特定版本的代码,而不是最新的。)

更新了备注:

  1. 关于其他一些答案 - 如果你知道输出的长度,你不需要StringBuilder,并且在使用ToCharArray时,这会创建并填充数组(你不需要先创建一个空数组)
  2. 与其他一些答案有关 - 你应该使用NextBytes,而不是一次获得一个表现
  3. 从技术上讲,您可以固定字节数组以便更快地访问..当您在字节数组上迭代超过6-8次时,通常是值得的。 (这里没有)
  4. 使用 RNGCryptoServiceProvider获得最佳随机性
  5. 使用缓存1MB随机数据缓冲区 - 基准测试显示缓存单字节访问速度快〜1000倍 - 超过1MB需要9ms而未缓存需要989ms。
  6. 在我的新班级中优化了对偏见区的拒绝
  7. 结束问题的解决方案:

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

    但是你需要我的新(未经测试)课程:

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

    对于历史记录 - 我对此答案的旧解决方案,使用随机对象:

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

    性能:

    1. SecureFastRandom - 首次单次运行 = ~9-33ms 。感觉不到的。 正在进行 5ms (有时它会超过13毫秒)超过10,000次迭代,单次平均迭代= 1.5微秒。。注意:通常需要2,但有时最多需要8次缓存刷新 - 取决于多少个单字节超过偏置区
    2. 随机 - 首次单次运行 = ~0-1ms 。感觉不到的。 正在进行 5ms 超过10,000次迭代。单次平均迭代= .5微秒。。大约相同的速度。
    3. 同时退房:

      这些链接是另一种方法。缓冲可以添加到这个新的代码库中,但最重要的是探索消除偏见的不同方法,并对速度和优缺点进行基准测试。

答案 17 :(得分:4)

可怕,我知道,但我无法自拔:


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

答案 18 :(得分:4)

我正在寻找一个更具体的答案,我想控制随机字符串的格式并遇到过这篇文章。例如:车牌(车辆)具有特定格式(每个国家),我想创建随机牌照 我决定为此编写自己的Random扩展方法。 (这是为了重用相同的Random对象,因为你可以在多线程场景中使用双倍)。 我创建了一个要点(https://gist.github.com/SamVanhoutte/808845ca78b9c041e928),但也会复制扩展类:

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 http://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings-in-c
        // Added logic to specify the format of the random string (# will be random string, 0 will be random numeric, other characters remain)
        StringBuilder result = new StringBuilder();
        for(int formatIndex = 0; formatIndex < format.Length ; formatIndex++)
        {
            switch(format.ToUpper()[formatIndex])
            {
                case '0': result.Append(getRandomNumeric(random)); break;
                case '#': result.Append(getRandomCharacter(random)); break;
                default : result.Append(format[formatIndex]); break;
            }
        }
        return result.ToString();
    }

    private static char getRandomCharacter(Random random)
    {
        string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        return chars[random.Next(chars.Length)];
    }

    private static char getRandomNumeric(Random random)
    {
        string nums = "0123456789";
        return nums[random.Next(nums.Length)];
    }
}

答案 19 :(得分:3)

尝试组合两个部分:唯一(序列,计数器或日期)和随机

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

试验:

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

答案 20 :(得分:2)

现在有单线风味。

private string RandomName
    {
        get
        {
            return new string(
                Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                    .Select(s =>
                    {
                        var cryptoResult = new byte[4];
                        using (var cryptoProvider = new RNGCryptoServiceProvider())
                            cryptoProvider.GetBytes(cryptoResult);
                        return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                    })
                    .ToArray());
        }
    }

答案 21 :(得分:2)

不使用Random的解决方案:

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

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

答案 22 :(得分:2)

以下是针对WinRT(Windows应用商店应用)的Eric J解决方案的变体,即加密声音:

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

如果性能很重要(特别是当长度很高时):

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

答案 23 :(得分:1)

我知道这不是最好的方法。但你可以试试这个。

string str = Path.GetRandomFileName(); //This method returns a random file name of 11 characters
str = str.Replace(".","");
Console.WriteLine("Random string: " + str);

答案 24 :(得分:1)

我不知道这是如何加密声音的,但它比迄今为止更复杂的解决方案(imo)更具可读性和简洁性,并且它应该更多随机&#34;比基于System.Random的解决方案。

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

我无法决定我认为这个版本或下一个版本是否更漂亮&#34;但它们会给出完全相同的结果:

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

当然,它并未针对速度进行优化,因此如果它的每周任务产生数百万随机字符串至关重要,请尝试另一个!

注意:此解决方案不允许重复使用字母表中的符号,并且字母表必须与输出字符串的大小相等或更大,这使得这种方法在某些情况下不太理想,这一切都取决于您的用例。

答案 25 :(得分:0)

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

答案 26 :(得分:0)

这是一种生成随机字母数字字符串的机制(我使用它来生成密码和测试数据)而不定义字母和数字,

CleanupBase64将删除字符串中的必要部分,并继续递归添加随机字母数字字母。

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

答案 27 :(得分:0)

如果你的值不是完全随机的,但实际上可能取决于某些东西 - 你可以计算一个'somwthing'的md5或sha1哈希值,然后将其截断到你想要的任何长度。

您也可以生成并截断guid。

答案 28 :(得分:0)

令人难以置信的nuget packages之一使这一过程变得如此简单。

var myObject = new Faker<MyObject>()
.RuleFor(p => p.MyAlphaNumericProperty, f => f.Random.AlphaNumeric(/*lenght*/ 7))
.Generate();

一个很好的例子是here

答案 29 :(得分:0)

不确定100%,因为我没有在这里测试所有选项,但是在我测试过的选项中,这是最快的。用秒表计时,并显示9-10滴答,所以如果速度比安全性更重要,请尝试以下操作:

    statusFunc = 0;

    ngOnInit() {

    var stopper = setInterval(function(){
    if (this.statusFunc == 1) {
        console.log(this.statusFunc);
        this.afterFirstSignal();
        clearInterval(stopper);
    }
  }, 2000);
 }

答案 30 :(得分:0)

对于加密和非加密,都有效:

private static readonly Random _random = new Random();

public static string GenerateRandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    RandomString(_random.NextBytes, length, charset.ToCharArray());

public static string GenerateRandomCryptoString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new System.Security.Cryptography.RNGCryptoServiceProvider())
        return RandomString(crypto.GetBytes, length, charset.ToCharArray());
}

private static string RandomString(Action<byte[]> fillRandomBuffer, int length, char[] charset)
{
    if (length < 0)
        throw new ArgumentOutOfRangeException(nameof(length), $"{nameof(length)} must be greater or equal to 0");
    if (charset is null)
        throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0)
        throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    var maxIdx = charset.Length;
    var chars = new char[length];
    var randomBuffer = new byte[length * 4];
    fillRandomBuffer(randomBuffer);

    for (var i = 0; i < length; i++)
        chars[i] = charset[BitConverter.ToUInt32(randomBuffer, i * 4) % maxIdx];

    return new string(chars);
}

使用发电机和LINQ。不是最快的选择(尤其是因为它不能一次生成所有字节),而是非常简洁且可扩展的:

private static readonly Random _random = new Random();

public static string GenerateRandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new string(_random.GetGenerator().RandomChars(charset.ToCharArray()).Take(length).ToArray());

public static string GenerateRandomCryptoString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new System.Security.Cryptography.RNGCryptoServiceProvider())
        return new string(crypto.GetGenerator().RandomChars(charset.ToCharArray()).Take(length).ToArray());
}

public static IEnumerable<char> RandomChars(this Func<uint, IEnumerable<uint>> randomGenerator, char[] charset)
{
    if (charset is null)
        throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0)
        throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    return randomGenerator((uint)charset.Length).Select(r => charset[r]);
}

public static Func<uint, IEnumerable<uint>> GetGenerator(this Random random)
{
    if (random is null)
        throw new ArgumentNullException(nameof(random));

    return GeneratorFunc_Inner;

    IEnumerable<uint> GeneratorFunc_Inner(uint maxValue)
    {
        if (maxValue > int.MaxValue)
            throw new ArgumentOutOfRangeException(nameof(maxValue));

        return Generator_Inner();

        IEnumerable<uint> Generator_Inner()
        {
            var randomBytes = new byte[4];
            while (true)
            {
                random.NextBytes(randomBytes);
                yield return BitConverter.ToUInt32(randomBytes, 0) % maxValue;
            }
        }
    }
}

public static Func<uint, IEnumerable<uint>> GetGenerator(this System.Security.Cryptography.RNGCryptoServiceProvider random)
{
    if (random is null)
        throw new ArgumentNullException(nameof(random));

    return Generator_Inner;

    IEnumerable<uint> Generator_Inner(uint maxValue)
    {
        var randomBytes = new byte[4];
        while (true)
        {
            random.GetBytes(randomBytes);
            yield return BitConverter.ToUInt32(randomBytes, 0) % maxValue;
        }
    }
}

使用LINQ的简单版本仅用于非加密字符串:

private static readonly Random _random = new Random();

public static string RandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new string(_random.GenerateChars(charset).Take(length).ToArray()); 

public static IEnumerable<char> GenerateChars(this Random random, string charset)
{
    if (charset is null) throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0) throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    return random.Generator(charset.Length).Select(r => charset[r]);
}

public static IEnumerable<int> Generator(this Random random, int maxValue)
{
    if (random is null) throw new ArgumentNullException(nameof(random));

    return Generator_Inner();

    IEnumerable<int> Generator_Inner() { while (true) yield return random.Next(maxValue); }
}

答案 31 :(得分:-1)

非常简单的解决方案。它使用ASCII值,只在它们之间生成“随机”字符。

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

}

答案 32 :(得分:-3)

您只需使用程序集SRVTextToImage。并在下面编写代码以生成随机字符串。

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

主要用于实现Captcha。但在你的情况下它也有效。希望它有所帮助。