C# 随机字符串生成器






4.90/5 (40投票s)
一个可以生成随机字符串并支持自定义的 C# 类。
引言
使用这个类,您可以生成诸如密码和标识符之类的随机字符串,但主要特点是您可以自定义它以满足您的需求。您无需修改代码,只需设置一些设置即可更改生成器的行为。
背景
我一直在寻找一个可以为标识符生成唯一随机字符串的 C# 类,但我找不到一个满足我所有需求的类,例如每种类型字符(大写字母、小写字母、数字和特殊字符)的最小数量或每个字符只使用一次。因此,我决定编写一个类,您可以在其中设置以下内容
- 四个字符集(大写、小写、数字和特殊字符)
- 设置您自己的字符集
- 每种字符类型的最小数量
- 模式驱动的字符串生成
- 唯一字符串生成
- 每个字符只使用一次
代码
总的来说,代码相当大,如果您愿意,您可以下载它,所以我只描述最重要的部分。
图例
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
是使用四个现有的字符集自动生成的:UseUpperCaseCharacters
、UseLowerCaseCharacters
、UseNumericCharacters
和 UseSpecialCharacters
。我相信在参数化阶段一次性生成它(比每次需要时都重新生成它)要快。
最后一个字符串生成算法基于模式生成字符串。它只是用来自相应集合的随机符号替换模式的字母。并且当然它会注意 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
所以有一些例子,例如
- 固定大小字符串生成
- 可变大小字符串生成
- 使用模式的字符串生成(L - 用于大写字母,l - 用于小写字母,n - 用于数字,s - 用于特殊字符,* - 用于任何字符(来自所有集合))
- 仅使用字母和数字的字符串生成
- 仅使用数字和特殊字符的字符串生成
- 使用自定义字母表进行生成
- 使用最小限制进行字符串生成
- 在生成期间每个字符只使用一次
- 使用多个设置
- 唯一字符串测试
历史
- 版本 1.1:进行了一些代码解释和优化。感谢评论。
- 版本 1.0:初始发布。