47

There is a library to generate Random numbers, so why isn't there a library for generation of random strings?

In other words how to generate a random string, and specify desired length, or better, generate unique string on specification you want i.e. specify the length, a unique string within my application is enough for me.

I know I can create a Guid (Globally Unique IDentifier) but those are quite long, longer they need to be.

int length = 8;
string s = RandomString.NextRandomString(length)
uniquestringCollection = new UniquestringsCollection(length)
string s2 = uniquestringCollection.GetNext();
CJBS
  • 15,147
  • 6
  • 86
  • 135
HCP
  • 1,012
  • 2
  • 11
  • 18
  • 3
    What are the legal characters allowed in the string? – Ani Jan 06 '11 at 15:45
  • It would be easy enough to write your own random string class (of course depending on a set of legal characters as pointed out by Ani). Unique strings on the other hand are a much tougher proposition - generating something that is unique across the world is pretty tough and the GUID does a good job of this using MAC address, timestamp and so on. I doubt it would be easy to do better. – John Pickup Jan 06 '11 at 15:48
  • Sounds relatively easy to implement (at least in a crude way). Are you looking for something more complicated than "generate a random character N times, check the whole thing against already generated strings, if not unique start over"? – Nellius Jan 06 '11 at 15:48
  • 2
    Libraries tend to only encapsulate functionality that's generally useful. I'm not sure what the usefulness of a random string is. – MusiGenesis Jan 06 '11 at 15:49
  • 1
    example of the usefullness are many: suppose you want to generate a lottery code , a name for you baby , suggests handles for a forum etc, etc. – HCP Jan 06 '11 at 15:58
  • What Nellius says, that is pretty much right on. I agree it is easy to implement, but it is a wast for every developer to implement it over and over again. Thus i think we should come up with a specification for a library – HCP Jan 06 '11 at 16:01
  • possible duplicate of [How can I generate random alphanumeric strings in C#?](http://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings-in-c) – CodesInChaos Apr 15 '14 at 08:27

11 Answers11

49

I can't recall where I got this, so if you know who originally authored this, please help me give attribution.

private static void Main()
{
    const string AllowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#@$^*()";
    Random rng = new Random();

    foreach (string randomString in rng.NextStrings(AllowedChars, (15, 64), 25))
    {
        Console.WriteLine(randomString);
    }

    Console.ReadLine();
}

private static IEnumerable<string> NextStrings(
    this Random rnd,
    string allowedChars,
    (int Min, int Max)length,
    int count)
{
    ISet<string> usedRandomStrings = new HashSet<string>();
    (int min, int max) = length;
    char[] chars = new char[max];
    int setLength = allowedChars.Length;

    while (count-- > 0)
    {
        int stringLength = rnd.Next(min, max + 1);

        for (int i = 0; i < stringLength; ++i)
        {
            chars[i] = allowedChars[rnd.Next(setLength)];
        }

        string randomString = new string(chars, 0, stringLength);

        if (usedRandomStrings.Add(randomString))
        {
            yield return randomString;
        }
        else
        {
            count++;
        }
    }
}
Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
  • 2
    Oooooh! I love the idea of using an IEnumerable for that. Snazzy! Just don't forget that Random isn't thread-safe and locking in an IEnumerable isn't generally a smart move. – Joshua Jan 06 '11 at 15:52
  • 4
    That's why the Random instance is passed into the method - it's then the caller's problem to take care of concurrency :) – Jesse C. Slicer Jan 06 '11 at 15:58
  • 2
    I've noticed this post getting a lot of attention recently. Hello to all. Allow me to direct you to Jon Skeet's article on thread-safe Random for additional awesomeness: http://msmvps.com/blogs/jon_skeet/archive/2009/11/04/revisiting-randomness.aspx – Jesse C. Slicer Nov 15 '11 at 14:53
  • 2
    The Jon Skeet blog link is now at https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness/ – berkeleybross Dec 28 '16 at 00:15
  • How is this guaranteed to be unique? (as the question preferred) – Mohammed Noureldin Oct 03 '18 at 14:25
  • 2
    It is the usedRandomStrings HashSet that controls uniqueness. – bkqc Jun 29 '22 at 20:28
32

How about-

static Random rd = new Random();
internal static string CreateString(int stringLength)
{
  const string allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789!@$?_-";
  char[] chars = new char[stringLength];

  for (int i = 0; i < stringLength; i++)
  {
    chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
  }

  return new string(chars);
}
David
  • 2,426
  • 3
  • 24
  • 36
Jason Quinn
  • 2,443
  • 3
  • 28
  • 36
  • 1
    I know this is insigfnificant, but you're missing capital letter "I", and lower-case letter "l" – Sasino Mar 20 '22 at 21:13
  • I really like this since it's simple and (like the accepted one) self contained. I'm using this for generating filename suffixes (as opposed to complete random filenames via [GetRandomFileName](https://learn.microsoft.com/en-us/dotnet/api/system.io.path.getrandomfilename?view=net-6.0)). They will be short and will be created from the main thread every time. Fits my needs perfectly. – CobaltBlue May 29 '23 at 20:21
11

How about

string.Join("", Enumerable.Repeat(0, 100).Select(n => (char)new Random().Next(127)));

or

var rand = new Random();
string.Join("", Enumerable.Repeat(0, 100).Select(n => (char)rand.Next(127)));
Ali Kleit
  • 3,069
  • 2
  • 23
  • 39
Ali Humayun
  • 1,756
  • 1
  • 15
  • 12
8

Random string using Concatenated GUIDs

This approach uses the minimum number of concatenated GUIDs to return a random string of the desired number of characters.

    /// <summary>
    /// Uses concatenated then SubStringed GUIDs to get a random string of the
    /// desired length. Relies on the randomness of the GUID generation algorithm.
    /// </summary>
    /// <param name="stringLength">Length of string to return</param>
    /// <returns>Random string of <paramref name="stringLength"/> characters</returns>
    internal static string GetRandomString(int stringLength)
    {
        StringBuilder sb = new StringBuilder();
        int numGuidsToConcat = (((stringLength - 1) / 32) + 1);
        for(int i = 1; i <= numGuidsToConcat; i++)
        {
            sb.Append(Guid.NewGuid().ToString("N"));
        }

        return sb.ToString(0, stringLength);
    }

Example output with a length of 8:

39877037
2f1461d8
152ece65
79778fc6
76f426d8
73a27a0d
8efd1210
4bc5b0d2
7b1aa10e
3a7a5b3a
77676839
abffa3c9
37fdbeb1
45736489

Example output with a length of 40 (note the repeated '4' - in a v4 GUID, thee is one hex digit that will always be a 4 (effectively removing 4 bits) -- the algorithm could be improved by removing the '4' to improve randomness, given that the returned length of the string can be less than the length of a GUID (32 chars)...):

e5af105b73924c3590e99d2820e3ae7a3086d0e3
e03542e1b0a44138a49965b1ee434e3efe8d063d
c182cecb5f5b4b85a255a397de1c8615a6d6eef5
676548dc532a4c96acbe01292f260a52abdc4703
43d6735ef36841cd9085e56f496ece7c87c8beb9
f537d7702b22418d8ee6476dcd5f4ff3b3547f11
93749400bd494bfab187ac0a662baaa2771ce39d
335ce3c0f742434a904bd4bcad53fc3c8783a9f9
f2dd06d176634c5b9d7083962e68d3277cb2a060
4c89143715d34742b5f1b7047e8107fd28781b39
2f060d86f7244ae8b3b419a6e659a84135ec2bf8
54d5477a78194600af55c376c2b0c8f55ded2ab6
746acb308acf46ca88303dfbf38c831da39dc66e
bdc98417074047a79636e567e4de60aa19e89710
a114d8883d58451da03dfff75796f73711821b02

C# Fiddler Demo: https://dotnetfiddle.net/Y1j6Dw

CJBS
  • 15,147
  • 6
  • 86
  • 135
  • please note that guids are designed for uniqueness, **NOT FOR SECURITY** - using guids as random string is bad idea (for more see https://blogs.msdn.microsoft.com/oldnewthing/20150701-00/?p=45241 or use your google-fu :) ) – Jan 'splite' K. Jan 22 '19 at 16:39
  • @Jan'splite'K. While your point about not using GUIDs as passwords is certainly true and accepted, I don't think there's an implication here that that's what they're being generated for. Personally, I used the above code as part of a test library to test populating strings in some automated tests... – CJBS Jan 24 '19 at 07:24
  • Sure, thats why i did not -1 your answer, just pointed out one known fact for random googlers like me :) (maybe i should write "using guids as password or token is bad idea") – Jan 'splite' K. Jan 24 '19 at 09:04
4

I commonly use code like the following to generate a random string:

internal static class Utilities {
  static Random randomGenerator = new Random();
  internal static string GenerateRandomString(int length) {
    byte[] randomBytes = new byte[randomGenerator.Next(length)];
    randomGenerator.NextBytes(randomBytes);
    return Convert.ToBase64String(randomBytes);
  }
}

This will create a Base64 encoded string of the random bytes generated by the random object. It isn't thread safe so multiple threads will have to lock around it. Additionally I use a static Random object so two calls to the method at the same time won't get the same initial seed.

Joshua
  • 8,112
  • 3
  • 35
  • 40
  • @CJBS bit of necro the byte array is also randomly sized in the code. So probably not the best way to do things if consistent length is required. – RubberChickenLeader Jul 10 '19 at 16:44
  • @RubberChickenLeader - yes that was the point of the fiddler example, to demonstrate variable output. – CJBS Jul 10 '19 at 18:55
2

A library for generating random strings wouldn't be very useful. It would either be too simple, so that you often need to replace it anyway, or too complex in order to be able to cover any possible situation, that you replace it because it's to complicated to use.

Creating random strings is quite easy by using the random geneator for numbers, given the exact details of your needs. It's just more efficient to write the code specifically for each situation.

If you want a unique string, there is two possibilities. You can either keep every random string that is created, so that you can check for uniqueness, or you can make it really long so that it's incredibly unlikely that there would be duplicates. A GUID does the latter (which explains why it's so long), so there is already an implementation for that.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Keeping the set of random strings seems like the better idea for my needs. In that case the strings don't need to be that long, making them easier to remember when needed. (And the values just need to be unique inside, not globally) – HCP May 05 '11 at 10:07
1

Sometimes a random string can be useful in something like a unit test, if it was me I would add the AutoFixture nuget package and then do something like this. In my example I need a 121 character string...

        var fixture = new Fixture();
        var chars = fixture.CreateMany<char>(121).ToArray();
        var myString = new string(chars);

If this wasn't in a unit test then I'd create myself a nuget package and use Autofixture in that, or something else if I needed only certain character types.

TheDex
  • 11
  • 1
0

You've sort of answered your own question; there is no RandomString() function because you can use a random number generator to generate a string easily.

1) Make the range of numbers between the ASCII characters that you wish to include

2) Append each character to a string until the desired length is reached.

3) Rise and repeat for each string needed (add them to an array, etc.)

Surely that'd do it?

Siyfion
  • 979
  • 1
  • 12
  • 32
  • True, although this just solved creating a random string. Not a unique string. – HCP May 04 '11 at 07:42
  • Ok, then just iterate through the array before each addition, checking for it's unique-ness. (As long as this can be done in a non-runtime critical maner?) – Siyfion May 05 '11 at 12:07
0

How about something like this...

static string GetRandomString(int lenOfTheNewStr)
{
    string output = string.Empty;
    while (true)
    {
        output = output + Path.GetRandomFileName().Replace(".", string.Empty);    
        if (output.Length > lenOfTheNewStr)
        {
            output = output.Substring(0, lenOfTheNewStr);
            break;
        }
    }
    return output;
}

Output

static void Main(string[] args)
{            
    for (int x = 0; x < 10; x++)
    {
        string output = GetRandomString(20);
        Console.WriteLine(output);
    }
    Console.ReadKey();
}

 

r323afsluywgozfpvne4
qpfumdh3pmskleiavi3x
nq40h0uki2o0ptljxtpr
n4o0rzwcz5pdvfhmiwey
sihfvt1pvofgxfs3etxg
z3iagj5nqm4j1f5iwemg
m2kbffbyqrjs1ad15kcn
cckd1wvebdzcce0fpnru
n3tvq0qphfkunek0220d
ufh2noeccbwyfrtkwi02

Online Demo: https://dotnetfiddle.net/PVgf0k


References
https://www.dotnetperls.com/random-string

DxTx
  • 3,049
  • 3
  • 23
  • 34
0
public  static String getAlphaNumericString(int n) {

        String AlphaNumericString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "abcdefghijklmnopqrstuvxyz";

        StringBuilder sb = new StringBuilder(n);

        for (int i = 0; i < n; i++) {

            // generate a random number between
            // 0 to AlphaNumericString variable length
            int index = (int) (AlphaNumericString.length() * Math.random());

            // add Character one by one in end of sb
            sb.append(AlphaNumericString.charAt(index));
        }

        return sb.toString();
    }
Alexandros Kourtis
  • 539
  • 2
  • 6
  • 20
-1

Here is some modification from above answers.

  private static string GetFixedLengthStrinng(int len)
    {
        const string possibleAllChars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789!@#$%^&*()_+{}:',.?/";
        StringBuilder sb = new StringBuilder();
        Random randomNumber = new Random();
        for (int i = 0; i < len; i++)
        {
            sb.Append(possibleAllChars[randomNumber.Next(0, possibleAllChars.Length)]);
        }
        return sb.ToString();
    }
  • 1
    `Random randomNumber = new Random();` should be statically declared external to the `GetFixedLengthString` method otherwise you will get the same string returned back on every call to the method within the same execution of your program. – Adrian Sanguineti Mar 12 '20 at 04:22