A Simplistic Random String Generation Snippet
This is just a little snippet that generates a random string, containing both upper and lower case characters and special chars, so there’s a range of 93 possible characters, taken from the UTF-8 character table. I thought I’d post it as the snippets I’ve seen after a quick search usually just generate strings with characters ranging from ‘A’ to ‘Z’, or do not work with properly initialized seeds.
Note that this method uses a static int field (seedCounter) when in comes to creating a random seed. This counter is incremented in a thread safe manner every time the method is being invoked. This simple trick is a simple workaround to the notoriously unreliable Random class, and effectively prevents double seeds (and thus: duplicate “random strings”) if the GetRandomString method is being invoked several times immediately. As an alternative, you could also use a static Random field, which would only have to be initialized once. My implementation has the smaller footprint (and integer variable), while a Random field would perform much better (currently, every invocation calculates a seed and creates a new Random instance). The better choice depends on the context I guess:
/// <summary> /// A counter that is being incremented with every invocation of /// <see cref="GetRandomString"/>. /// </summary> private static int seedCounter = (int)DateTime.Now.Ticks; /// <summary> /// Generates a random string of a given length, which consists /// of characters taken from the UTF-8 table (0x21 - 0x7e). /// </summary> /// <param name="length">The length of the random string.</param> /// <returns>Random characters.</returns> public static string GetRandomString(int length) { const int lower = 0x21; const int upper = 0x7e; StringBuilder builder = new StringBuilder(); //increment thread-safe seedCounter = Interlocked.Increment(ref seedCounter); //create random with the seed (make sure it's not int.MinValue) Random rnd = new Random(seedCounter %int.MinValue); for (int i = 0; i < length; i++) { builder.Append((char) rnd.Next(lower, upper)); } return builder.ToString(); }
Accordingly, invoking the method like this:
string random = GetRandomString(10);
…generates you a string comparable to this one: 2#,R`6>Cz{
If you want a cryptographically secure random string, you should use the System.Security.Cryptography.RandomNumberGenerator class instead of the System.Random class:
public static string GetRandomString(int length)
{
if (0 >= length) throw new ArgumentOutOfRangeException();
const byte lower = 0x21;
const byte upper = 0x7e;
int resultIndex = 0;
char[] result = new char[length];
byte[] buffer = new byte[length];
var rnd = RandomNumberGenerator.Create();
while (resultIndex lower <= b && b (char)b).ToArray();
if (0 != temp.Length)
{
int l = Math.Min(temp.Length, length – resultIndex);
Array.Copy(temp, 0, result, resultIndex, l);
resultIndex += l;
}
}
return new String(result);
}
OK, the comments don’t like less-than characters!
public static string GetRandomString(int length)
{
if (0 >= length) throw new ArgumentOutOfRangeException();
const byte lower = 0x21;
const byte upper = 0x7e;
int resultIndex = 0;
char[] result = new char[length];
byte[] buffer = new byte[length];
var rnd = RandomNumberGenerator.Create();
while (resultIndex < length)
{
rnd.GetNonZeroBytes(buffer);
char[] temp = buffer.Where(b => lower <= b && b <= upper).Select(b => (char)b).ToArray();
if (0 != temp.Length)
{
int l = Math.Min(temp.Length, length – resultIndex);
Array.Copy(temp, 0, result, resultIndex, l);
resultIndex += l;
}
}
return new String(result);
}