tags:

views:

35147

answers:

10

I've been looking for a simple java algorithm to generate a pseudo-random alpha-numeric string. In my situation it would be used as a unique session/key identifier that would "likely" be unique over 500K+ generation (my needs don't really require anything much more sophisticated) . Ideally I would be able to specify a length depending on my uniqueness needs. For example, a generated string of length 12 might look something like "AEYGF7K0DM1X".

Answers: I like @Apocalisp and @erickson's answers equally well. The only downside to @Apocalisp's answer is it requires an apache class. Thanks to both for the help!

+26  A: 

Here is code for secure, easy, but a little bit more expensive session identifiers.

import java.security.SecureRandom;

public final class SessionIdentifierGenerator
{

  private SecureRandom random = new SecureRandom();

  public String nextSessionId()
  {
    return new BigInteger(130, random).toString(32);
  }

}

If you allow session identifiers to be easily guessable (too short, flawed random number generator, etc.), attackers can hijack other's sessions. Note that SecureRandom objects are expensive to initialize, so you'll want to keep one around and reuse it.

Here is alternative code for cheap, insecure random alpha-numeric strings. You can tweak the "symbols" if you want to use more characters.

import java.util.Random;

public class RandomString
{

  private static final char[] symbols = new char[36];

  static {
    for (int idx = 0; idx < 10; ++idx)
      symbols[idx] = (char) ('0' + idx);
    for (int idx = 10; idx < 36; ++idx)
      symbols[idx] = (char) ('a' + idx - 10);
  }

  private final Random random = new Random();

  private final char[] buf;

  public RandomString(int length)
  {
    if (length < 1)
      throw new IllegalArgumentException("length < 1: " + length);
    buf = new char[length];
  }

  public String nextString()
  {
    for (int idx = 0; idx < buf.length; ++idx) 
      buf[idx] = symbols[random.nextInt(symbols.length)];
    return new String(buf);
  }

}
erickson
your expensive way does not work for me! i get cannot find symbol for method BigInteger(int,java.security.SecureRandom)
ufk
@ufk - It sounds like you left out the `new` operator, since the compiler complains it can't find a "method," rather than a constructor.
erickson
+3  A: 

Here it is in Java:

import static java.lang.Math.round;
import static java.lang.Math.random;
import static java.lang.Math.pow;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static org.apache.commons.lang.StringUtils.leftPad

public class RandomAlphaNum {
  public static String gen(int length) {
    StringBuffer sb = new StringBuffer();
    for (int i = length; i > 0; i -= 12) {
      int n = min(12, abs(i));
      sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0'));
    }
    return sb.toString();
  }
}

Here's a sample run:

scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy
Apocalisp
+31  A: 

Java supplies a way of doing this directly. If you don't want the dashes, they are easy to strip out.

String uuid = UUID.randomUUID().toString();
System.out.println("uuid = " + uuid);

Output:

uuid = 2d7428a6-b58c-4008-8575-f05549f16316

Steve McLeod
A: 

I found this solution that generates a random hex encoded string. The provided unit test seems to hold up to my primary use case. Although, it is slightly more complex than some of the other answers provided.

/**
 * Generate a random hex encoded string token of the specified length
 *  
 * @param length
 * @return random hex string
 */
public static synchronized String generateUniqueToken(Integer length) 
{

    byte random[] = new byte[length];
    Random randomGenerator = new Random();
    StringBuffer buffer = new StringBuffer();

    randomGenerator.nextBytes(random);

    for (int j = 0; j < random.length; j++)
    {
        byte b1 = (byte) ((random[j] & 0xf0) >> 4);
        byte b2 = (byte) (random[j] & 0x0f);
        if (b1 < 10)
            buffer.append((char) ('0' + b1));
        else
            buffer.append((char) ('A' + (b1 - 10)));
        if (b2 < 10)
            buffer.append((char) ('0' + b2));
        else
            buffer.append((char) ('A' + (b2 - 10)));
    }

    return (buffer.toString());
}

@Test
public void testGenerateUniqueToken()
{
    Set set = new HashSet();
    String token = null;

    /* Seems like we should be able to generate 500K tokens 
     * without a duplicate 
    */
    for (int i=0; i<500000; i++)
    {
        token = Utility.generateUniqueToken(16);

        if (set.contains(token)) 
        {
            fail("Duplicate token generated");
        }
        else
        {
            set.add(token);
        }
    }

}
Todd
+11  A: 

If you're happy to use Apache classes, why not just use org.apache.commons.lang.RandomStringUtils (commons-lang)

http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/RandomStringUtils.html

cmsherratt
It seems to me that apache commons libs can solve a good 20% of the java questions asked on stackoverflow....
skaffman
Correction to the dead link above: http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/RandomStringUtils.html
Gary Rowe
+2  A: 
static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static Random rnd = new Random();

String randomString( int len ) 
{
  StringBuilder sb = new StringBuilder( len );
  for( int i = 0; i < len; i++ ) sb.append( AB[ rnd.nextInt(AR.length()) ] );
  return sb.toString();
}
maxp
It should read: sb.append( alpha.substring( random.nextInt(alpha.length()) ) )
Abdul
A: 

Hi this is Amar ([email protected]) from Hyderabad. I have developed an application to develop an auto generated alphanumberic string for my project. In this string the first three chars are alphabets and the next seven are integers.

the code is

public class AlphaNumericGenerator {

public static void main(String[] args) {
    java.util.Random r = new java.util.Random();
    int i = 1, n = 0;
    char c;
    String str="";
    for (int t = 0; t < 3; t++) {
        while (true) {
            i = r.nextInt(10);
            if (i > 5 && i < 10) {

                if (i == 9) {
                    i = 90;
                    n = 90;
                    break;
                }
                if (i != 90) {
                    n = i * 10 + r.nextInt(10);
                    while (n < 65) {
                        n = i * 10 + r.nextInt(10);
                    }
                }

                break;
            }
        }
        c=(char)n;

        str= String.valueOf(c)+str;
    }
    while(true){
    i = r.nextInt(10000000);
    if(i>999999)
        break;
    }
    str=str+i;
    System.out.println(str);

}

}

+5  A: 

in one line-

Long.toHexString(Double.doubleToLongBits(Math.random()));

http://mynotes.wordpress.com/2009/07/23/java-generating-random-string/

A: 

using Dollar should be simple as:

// "0123456789" + "ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();

String randomString(int length) {
    return $(validCharacters).shuffle().slice(12).toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int i : $(5)) {
        System.out.println(randomString(12));
    }
}

it outputs something like that:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7
dfa
A: 

Actually nice sample codes.

bhathiya