65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 随机字符串生成器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (40投票s)

2012 年 7 月 17 日

CPOL

3分钟阅读

viewsIcon

211410

downloadIcon

8351

一个可以生成随机字符串并支持自定义的 C# 类。

引言

使用这个类,您可以生成诸如密码和标识符之类的随机字符串,但主要特点是您可以自定义它以满足您的需求。您无需修改代码,只需设置一些设置即可更改生成器的行为。

背景

我一直在寻找一个可以为标识符生成唯一随机字符串的 C# 类,但我找不到一个满足我所有需求的类,例如每种类型字符(大写字母、小写字母、数字和特殊字符)的最小数量或每个字符只使用一次。因此,我决定编写一个类,您可以在其中设置以下内容

  1. 四个字符集(大写、小写、数字和特殊字符)
  2. 设置您自己的字符集
  3. 每种字符类型的最小数量
  4. 模式驱动的字符串生成
  5. 唯一字符串生成
  6. 每个字符只使用一次

代码

总的来说,代码相当大,如果您愿意,您可以下载它,所以我只描述最重要的部分。 

图例

  • Green - 公共方法
  • Red - 私有方法
  • Blue - 内部数据

用户有三个选项:生成固定大小的字符串、可变大小的字符串或模式驱动的字符串生成。它们稍后都将调用通用的 GenerateString 方法,该方法将检查异常情况并调用三种算法之一来生成字符串(就像策略模式一样)。最后,它会检查此字符串是否唯一,如果我们需要一个唯一的字符串并且生成的字符串不是唯一的,那么它会重新调用自身(递归地,因此在生成大量具有大量限制的小字符串时,您可能会得到堆栈溢出异常)。我使用 RNGCryptoServiceProvider 来获取随机数,但如果您希望生成速度更快,您可以将其更改为普通的 Random

此方法通过确定将使用哪种算法来生成字符串。

private string GenerateString(int length)
{
    if (length == 0)
       throw new ArgumentException("You can't generate a string of a zero length");
    if (!UseUpperCaseCharacters && !UseLowerCaseCharacters && !UseNumericCharacters && !UseSpecialCharacters)
       throw new ArgumentException("There should be at least one character set in use");
    if (!RepeatCharacters && (CurrentGeneralCharacters.Length < length))
       throw new ArgumentException("There is not enough characters to create a string without repeats");
    string result = ""; // This string will contain the result
    if (PatternDriven)
    {
       // Using the pattern to generate a string
       result = PatternDrivenAlgo(Pattern);
    }
    else if (MinUpperCaseCharacters == 0 && MinLowerCaseCharacters == 0 &&
             MinNumericCharacters == 0 && MinSpecialCharacters == 0)
    {
       // Using the simpliest algorithm in this case
       result = SimpleGenerateAlgo(length);
    }
    else
    {
       // Paying attention to limits
       result = GenerateAlgoWithLimits(length);
    }
       // Support for unique strings
       // Recursion, but possibility of the stack overflow is low for big strings (> 3 chars).
       if (UniqueStrings && ExistingStrings.Contains(result))
           return GenerateString(length);
       AddExistingString(result); // Saving history
       return result;
}

用于字符串生成的最简单算法。它仅针对所有限制调用(例如,MinUpperCaseCharacters 等于 0)。

private string SimpleGenerateAlgo(int length)
{
   string result = "";
   // No special limits
   for (int i = 0; i < length; i++)
   {
      char newChar = CurrentGeneralCharacters[GetRandomInt() % CurrentGeneralCharacters.Length];
      if (!RepeatCharacters && result.Contains(newChar))
      {
         do
         {
            newChar = CurrentGeneralCharacters[GetRandomInt() % CurrentGeneralCharacters.Length];
         } while (result.Contains(newChar));
      }
         result += newChar;
   }
   return result;
}

字符串生成算法,注意限制。

private string GenerateAlgoWithLimits(int length)
{
  // exceptional situations
  if (MinUpperCaseCharacters + MinLowerCaseCharacters +
    MinNumericCharacters + MinSpecialCharacters > length)
  {
    throw new ArgumentException("Sum of MinUpperCaseCharacters, MinLowerCaseCharacters," +
    " MinNumericCharacters and MinSpecialCharacters is greater than length");
  }
  if (!RepeatCharacters && (MinUpperCaseCharacters > CurrentUpperCaseCharacters.Length))
    throw new ArgumentException("Can't generate a string with this number of MinUpperCaseCharacters");
  if (!RepeatCharacters && (MinLowerCaseCharacters > CurrentLowerCaseCharacters.Length))
    throw new ArgumentException("Can't generate a string with this number of MinLowerCaseCharacters");
  if (!RepeatCharacters && (MinNumericCharacters > CurrentNumericCharacters.Length))
    throw new ArgumentException("Can't generate a string with this number of MinNumericCharacters");
  if (!RepeatCharacters && (MinSpecialCharacters > CurrentSpecialCharacters.Length))
    throw new ArgumentException("Can't generate a string with this number of MinSpecialCharacters");
  int AllowedNumberOfGeneralChatacters = length - MinUpperCaseCharacters - MinLowerCaseCharacters
  - MinNumericCharacters - MinSpecialCharacters;
  
  string result = "";
  // generation character set in order to support unique characters
  List<char> Characters = new List<char>();
  
  // adding chars to an array
  for (int i = 0; i < MinUpperCaseCharacters; i++)
    Characters.Add(GetRandomCharFromArray(UpperCaseCharacters,Characters));
  for (int i = 0; i < MinLowerCaseCharacters; i++)
    Characters.Add(GetRandomCharFromArray(LowerCaseCharacters, Characters));
  for (int i = 0; i < MinNumericCharacters; i++)
    Characters.Add(GetRandomCharFromArray(NumericCharacters, Characters));
  for (int i = 0; i < MinSpecialCharacters; i++)
    Characters.Add(GetRandomCharFromArray(SpecialCharacters, Characters));
  for (int i = 0; i < AllowedNumberOfGeneralChatacters; i++)
    Characters.Add(GetRandomCharFromArray(CurrentGeneralCharacters, Characters));
  
  // generating result
    for (int i = 0; i < length; i++)
    {
      int position = GetRandomInt() % Characters.Count;
      char CurrentChar = Characters[position];
      Characters.RemoveAt(position);
      result += CurrentChar;
    }
    return result;
}

CurrentGeneralCharacters 是使用四个现有的字符集自动生成的:UseUpperCaseCharactersUseLowerCaseCharactersUseNumericCharactersUseSpecialCharacters。我相信在参数化阶段一次性生成它(比每次需要时都重新生成它)要快。

最后一个字符串生成算法基于模式生成字符串。它只是用来自相应集合的随机符号替换模式的字母。并且当然它会注意 RepeatCharacters 标志。

private string PatternDrivenAlgo(string Pattern)
{
    string result = "";
    List<char> Characters = new List<char>();
    foreach (char character in Pattern.ToCharArray())
    {
        char newChar = ' ';
        switch (character)
        {
            case 'L':
            {
                newChar = GetRandomCharFromArray(CurrentUpperCaseCharacters, Characters);
                break; 
            }
            case 'l':
            {
                newChar = GetRandomCharFromArray(CurrentLowerCaseCharacters, Characters);
                break; 
            }
            case 'n':
            {
                newChar = GetRandomCharFromArray(CurrentNumericCharacters, Characters);
                break; 
            }
            case 's':
            {
                newChar = GetRandomCharFromArray(CurrentSpecialCharacters, Characters);
                break;   
            }
            case '*':
            {
                newChar = GetRandomCharFromArray(CurrentGeneralCharacters, Characters);
                break;  
            }
            default:
            {
                throw new Exception("The character '" + character + "' is not supported");
            }
        }
        Characters.Add(newChar);
        result += newChar;
    }
    return result;
}

使用代码

要开始使用它,您需要创建一个类的实例并像这样调用 Generate

Console.WriteLine("Fixed size");
RandomStringGenerator RSG = new RandomStringGenerator();
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(25));

Console.WriteLine("Variable size");
RSG = new RandomStringGenerator();
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(15,25));

Console.WriteLine("Using pattern");
RSG = new RandomStringGenerator();
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate("LLln*ssssL"));

Console.WriteLine("Using only letters and numbers");
RSG = new RandomStringGenerator();
// Or we can use the constructor
RSG.UseSpecialCharacters = false;
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(30));

Console.WriteLine("Using only special characters and numbers");
RSG = new RandomStringGenerator();
// Or we can use the constructor
RSG.UseUpperCaseCharacters = false;
RSG.UseLowerCaseCharacters = false;
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(30));
 
Console.WriteLine("Using your own alphabet");
RSG = new RandomStringGenerator(false,true,true,false);
// Or we can use the constructor
RSG.LowerCaseCharacters = "абвгдежзиклмнопрстуфхчшщюяьъ".ToCharArray();
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(30));

Console.WriteLine("Using special limits");
RSG = new RandomStringGenerator();
RSG.MinLowerCaseCharacters = 2;
RSG.MinSpecialCharacters = 20;
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(35));

Console.WriteLine("Using each character only once");
RSG = new RandomStringGenerator();
RSG.MinLowerCaseCharacters = 25;
RSG.RepeatCharacters = false;
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate(25));

Console.WriteLine("Using custom alphabet, pattern and unique chars");
RSG = new RandomStringGenerator();
RSG.LowerCaseCharacters = "абвгдежзиклмнопрстуфхчшщюяьъ".ToCharArray();
RSG.RepeatCharacters = false;
for (int i = 0; i < 5; i++)
    Console.WriteLine(RSG.Generate("lllnlllnlllsssL"));

Console.WriteLine("Unique strings test");
RSG = new RandomStringGenerator(false,false,true,false); // numbers only
RSG.UniqueStrings = true;
for (int i = 0; i < 9; i++)
    Console.WriteLine(RSG.Generate(1));

这将产生以下结果

Fixed size

dDDH6S%5we=h:9=Ohm2qZ_CPm
v{]q.sIY@1|YVc/y<Pu=oY[gn
i%Ws!(X%YOQ8uc?50uf#r(OC[
kTJQ|>m*N1CA_qP>-J=%elHp[
GZaAuwdwBR<T/$9-5,pJNDn>r

Variable size

LfUf%kcb{4A#bHOlwHtX8
kX>uBUIOcU6>>mTx
$:wo)KCs=B;c{Rfz.}MLtD
V4*zH6yjQuszcZNkrz_7
mblAFP#_=b>el<>CelyS.

Using pattern

JVh8I~.=>B
JJa8d,%?]M
BXv7?{]%]I
GFz5S&!|(U
PEu8m~(%(Z

Using only letters and numbers

jbIBUPvKNc0sOsnRSVFbK43k7sVnGi
V1UdOnJtR3GUPE9lcgG6W0xbo8ibMI
y2ecnrzPJcQ74Qcewu7YHdHS5eauwm
eBYufP01BMbSddsT7tJ9MevNSnVDE8
tU3jcbB7yuHknMWDphazYSNO9QBvXm

Using only special characters and numbers

$*&!.<>52]$(89}+}]$]]5<67_03~>
~&;>#3!(4|2<1*>>$.#&?#)8+$?>0|
@^@*@.</^},>-*!61^&]-~}?}={(5|
!:{3;>{}9*3<;3:5{3,+?19}04?@./
|586<([11|.~>8*8?8]|)<>%([)0|6

Using your own alphabet

ообкбнълея4тжд8ик3л924р7псу5дя
6н2рхьрр4ш65зс35бх8ло4015ед8аж
рь4жаоупиет76хлхдпю2кщгд0о8сьг
гусю28жрж1щиьп7к8гблф7см48лб8д
сд8гч5щхчиж4чдщьс1нь9ичгщзабул

Using special limits

!I@%){.>f,S-_3k_^*s$~/$_)*>)({)%():
$[?-iQ~:~C;{a]{?^X,^g^;G{<!R{>,W]_*
?=~F>+*d}_]#9||C[*B[U^j[T%em&/r{_o.
:=K5-;1]Hg_!}+&$/9h(k-};g:%Iq#.{>GV
XP&o<;U(%:E<}L,ehi;//-:{/F2!&;!+^>@

Using each character only once

lvpeiywofrhkajdqtxcsbunzm
enfkasgqtlxzuciryjmpdbohv
oyfjnxkqtamcvzipwlsedhurb
atubmnkehwjvolzpgxfsdicqy
swqkdatpgzcjhmiyvblxnufro

Using custom alphabet, pattern and unique chars

ъхг6тею1ушь]->G
юхч8ьта7щгш)>@H
ащо8ефл0ъпз};!K
ъут8ещш5иом^$|K
ожх5ргн9тсш?~#M

Unique strings test
4
1
3
5
0
9
6 
2
7
8

所以有一些例子,例如

  1. 固定大小字符串生成
  2. 可变大小字符串生成
  3. 使用模式的字符串生成(L - 用于大写字母,l - 用于小写字母,n - 用于数字,s - 用于特殊字符,* - 用于任何字符(来自所有集合))
  4. 仅使用字母和数字的字符串生成
  5. 仅使用数字和特殊字符的字符串生成
  6. 使用自定义字母表进行生成
  7. 使用最小限制进行字符串生成
  8. 在生成期间每个字符只使用一次
  9. 使用多个设置
  10. 唯一字符串测试

历史  

  • 版本 1.1:进行了一些代码解释和优化。感谢评论。
  • 版本 1.0:初始发布。
© . All rights reserved.