This question already has answers here:
How to generate a random alpha-numeric string
(46 answers)
Closed 6 years ago.
I'm trying to generate a string between capital A-Z in java using Secure Random. Currently I'm able to generate an alphanumeric string with special characters but I want a string with only upper case alphabets.
public String createRandomCode(int codeLength, String id){
char[] chars = id.toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new SecureRandom();
for (int i = 0; i < codeLength; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
String output = sb.toString();
System.out.println(output);
return output ;
}
The input parameters are length of the output string & id whhich is alphanumeric string.Can't understand what modifications to make to the above code to generate only upper case alphabet string. Please help..
Your method randomly selects characters out of the id argument. If you want those to only be uppercase letters, then pass a string with those characters:
String randomCode = createRandomCode(length, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
EDIT If you want to avoid duplicates, you can't just select characters at random. You'll want to shuffle them and pick out the first n characters:
public String createRandomCode(int codeLength, String id) {
List<Character> temp = id.chars()
.mapToObj(i -> (char)i)
.collect(Collectors.toList());
Collections.shuffle(temp, new SecureRandom());
return temp.stream()
.map(Object::toString)
.limit(codeLength)
.collect(Collectors.joining());
}
EDIT 2 Just for fun, here's another way to implement the original random code generator (allowing duplicates):
public static String createRandomCode(int codeLength, String id) {
return new SecureRandom()
.ints(codeLength, 0, id.length())
.mapToObj(id::charAt)
.map(Object::toString)
.collect(Collectors.joining());
}
Here is generator that I wrote and use:
public class RandomGenerator {
private static final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static String generateRandom(int length) {
Random random = new SecureRandom();
if (length <= 0) {
throw new IllegalArgumentException("String length must be a positive integer");
}
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(characters.charAt(random.nextInt(characters.length())));
}
return sb.toString();
}
}
in numChars string you can put any characters you want to be included. int length parameter is the length of generated random string.
Here is an example method that uses the int range for characters A to Z (also this method avoids duplicate characters in the String) :
public String createRandomCode(final int codeLength) {
int min = 65;// A
int max = 90;// Z
StringBuilder sb = new StringBuilder();
Random random = new SecureRandom();
for (int i = 0; i < codeLength; i++) {
Character c;
do {
c = (char) (random.nextInt((max - min) + 1) + min);
} while (sb.indexOf(c.toString()) > -1);
sb.append(c);
}
String output = sb.toString();
System.out.println(output);
return output;
}
The range part comes from this topic : Generating random integers in a specific range
Related
This question already has answers here:
Randomize the letters in the middle of the word, while keeping the first and last letters unchanged
(5 answers)
Closed 10 months ago.
I am trying to change the place of characters in a string. The first and last have to stay like they are.
For example:
String str = "String test print out";
The output should be for example:
Sirntg tset pirnt out
The first and last character of each word have to stay the rest have to change randomly:
Here is the code I already did, I tried to split the element of the string in an array and split them, but it's not working:
import java.util.*;
public class Main
{
public static void main(String[] args) {
String str = "String test out";
String[] words = str.split("\\s");
Random rnd = new Random();
ArrayList<Integer> digitList = new ArrayList<Integer>();
for(int j = 0;0<=words[].length();j++){
int lst = words[j].length();
char first = words[j].charAt(0);
char last = words[j].charAt(words[j].length() - 1);
for(int i =1, random = 0; i < words[j].length()-1; i++){
do{
random = rnd.nextInt(words[j].length()-2)+1;
}while(digitList.contains(random));
digitList.add(random);
System.out.print(words[j].charAt(random));
}
}
}
}
You could make use of some nifty functionality in Java's collection framework:
public static void main(String[] args) {
String str = "String test out";
for (String word : str.split("\\s")) {
List<Character> chars = word.chars()
.mapToObj(e -> (char) e)
.collect(Collectors.toList());
// shuffle the letters in the word, except for the first one and last one
Collections.shuffle(chars.subList(1, chars.size() - 1));
String shuffledWord = chars.stream()
.map(String::valueOf)
.collect(Collectors.joining());
System.out.println(shuffledWord);
}
}
Here is a really efficient way to do it. Instead of splitting, changing strings and merging them back together, create a single StringBuilder and use a Pattern to go through each word, scramble them and then return the string.
/** This pattern matches a word, and group 1 excludes the first and last letter. */
static final Pattern WORD = Pattern.compile("\\b\\w(\\w{2,})\\w\\b");
public String scrambleWords(String input) {
Random random = new Random();
StringBuilder s = new StringBuilder(input);
Matcher m = WORD.matcher(input);
while (m.find()) {
int start = m.start(1);
int end = m.end(1);
for (int i = start; i + 1 < end; i++) {
int j = random.nextInt(i + 1, end);
char c1 = s.charAt(i);
char c2 = s.charAt(j);
s.setCharAt(i, c2);
s.setCharAt(j, c1);
}
}
return s.toString();
}
Im working on an assignment for school where i am going to finish a short password generator.
when trying to loop adding characters out of the string, it ends up adding the same character, but if i would just print out characters it gives different ones. could someone explain why this is? i would really like to learn.
private void program() {
System.out.println(generate(all));
}
Random rand = new Random();
String all = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int randomInt = rand.nextInt(all.length());
char randomchar = all.charAt(randomInt);
StringBuilder sb = new StringBuilder();
String generate (String string) {
while (sb.length() < 10) {
sb.append(randomchar);
}
return sb.toString();
}
}
You are setting nextInt and nextChar gloabally. This need to be moved to your generation method.
String generate (String string) {
StringBuilder sb = new StringBuilder();
while (sb.length() < 10) {
int randomInt = rand.nextInt(all.length());
char randomchar = all.charAt(randomInt);
sb.append(randomchar);
}
return sb.toString();
}
Size your StringBuilder for efficiency (and big passwords)
public String generatePassword(String candidateChars, int passwordLength) {
Random rand = new Random();
int max = candidateChars.length();
StringBuilder sb = new StringBuilder(passwordLength);
for (int i = 0; i < passwordLength; i++) {
char randomchar = candidateChars.charAt(rand.nextInt(max));
sb.append(randomchar);
}
return sb.toString();
}
You should (re-)generate randomInt as well as randomchar within loop:
while (sb.length() < 10) {
// we want fresh value on ach itteration
int randomInt = rand.nextInt(all.length());
char randomchar = all.charAt(randomInt);
sb.append(randomchar);
}
What is the most simple way? Minimizing any imports.
This one is good:
String str = Long.toHexString(Double.doubleToLongBits(Math.random()));
But it's not perfect, for example it complicates with custom length.
Also an option: How to make this String unique?
Create a String of the characters which can be included in the string:
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Generate an integer using the Random class and use it to get a random character from the String.
Random random = new Random();
alphabet.charAt(random.nextInt(alphabet.length()));
Do this n times, where n is your custom length, and append the character to a String.
StringBuilder builder = new StringBuilder(n);
for (int i = 0; i < n; i++) {
builder.append(/* The generated character */);
}
Together, this could look like:
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
public String generateString(int length) {
Random random = new Random();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(ALPHABET.charAt(random.nextInt(ALPHABET.length())));
}
return builder.toString();
}
RandomStringUtils from commons-lang. If you don't wish to import, check out its source.
I'm interested in generating a (secure) random String with the following properties:
Atleast 1 upper case letter
Atleast 1 lower case letter
Atleast 1 digit from 0-9
Atleast one special char from chars $&#?<>~!%#
The length of string should be from 12-13 digits/chars long.
I know there is a class in Apache commons that can help generate random Strings however there is no option to include special chars.
I'm also aware of some other similar questions on SO however none of them address exactly these requirements.
I've tried the following so far:
import java.security.SecureRandom;
public final class SessionIdentifierGenerator {
private SecureRandom random = new SecureRandom();
public String nextSessionId() {
return
new BigInteger(130, random).toString(32);
}
}
But it does not contain char set from each of the 4 points.
I also tried:
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.charAt( rnd.nextInt(AB.length())));
return sb.toString();
}
I know I can modify the String AB to include special chars but there's no way to guarantee string will contain Atleast 1 upper, 1 lower, 1 digit and 1 special char.
I'm using Java.
The easiest way in your case is to generate the random password containing any of allowed symbols, then test whether the criteria met:
private static final String symbols =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$&#?<>~!%#";
public static String genPassword(Random r) {
while(true) {
char[] password = new char[r.nextBoolean()?12:13];
boolean hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;
for(int i=0; i<password.length; i++) {
char ch = symbols.charAt(r.nextInt(symbols.length()));
if(Character.isUpperCase(ch))
hasUpper = true;
else if(Character.isLowerCase(ch))
hasLower = true;
else if(Character.isDigit(ch))
hasDigit = true;
else
hasSpecial = true;
password[i] = ch;
}
if(hasUpper && hasLower && hasDigit && hasSpecial) {
return new String(password);
}
}
}
According to my tests, number of required iterations rarely exceeds 5 and in more than half tests the first generated password meets the criteria. Though don't force your users to memoize such passwords! Here's how they look like:
c3h$oyuKcZZl
Si4e8F4sWjy#i
V$9WwW7zJ8ba
~9htwMwcFc!s
wBm94~AH%z%MU
p4TE36S&Y>J14
R9Bsqq#23eYk
PTfcvR5u?piZQ
CE8ot>a74PmZP
4zAco~P6Xuf3E
aiv?VDN4j9pE
Set up an array/list/whatever of characters. Pick a random lowercase letter and put it into your array. Pick a random uppercase letter and put it into your array. Pick a random digit and put it into your array. Pick a random special character and put it into your array. You have four characters in your array which partly meets your requirements.
Now pick as many more characters as you need at random from the string: "A-Za-z0-9$&#?<>~!%#" Add each selected character to your character array.
Now shuffle your character array to mess up the order of the first four characters.
Convert the shuffled array to a string.
The following works well for me. Note, that you could pass in a specific Random implementation if you didn't want to use RandomUtils.
public class RandomUtil {
public static final String ALPHABETIC_UPPERCASE_SYMBOLS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String ALPHABETIC_LOWERCASE_SYMBOLS = "abcdefghijklmnopqrstuvwxyz";
public static final String NUMERIC_SYMBOLS = "0123456789";
public static final String SPECIAL_SYMBOLS = "$&#?<>~!%#";
public static final String ALPHANUMERIC_AND_SPECIAL_SYMBOLS =
ALPHABETIC_UPPERCASE_SYMBOLS +
ALPHABETIC_LOWERCASE_SYMBOLS +
NUMERIC_SYMBOLS +
SPECIAL_SYMBOLS;
public static String generateRandomAlphanumericAndSpecialCharactersKey(int length) {
List<Character> chars = new ArrayList<>(length);
boolean hasUpper = false;
boolean hasLower = false;
boolean hasNumber = false;
boolean hasSpecial = false;
for (int i = 0; i < length; i++) {
// Make sure we have at least one upper, lower, number and special character.
// Then, fill randomly from set containing all characters.
if (!hasUpper) {
chars.add(ALPHABETIC_UPPERCASE_SYMBOLS.charAt(RandomUtils.nextInt(0, ALPHABETIC_UPPERCASE_SYMBOLS.length())));
hasUpper = true;
} else if (!hasLower) {
chars.add(ALPHABETIC_LOWERCASE_SYMBOLS.charAt(RandomUtils.nextInt(0, ALPHABETIC_LOWERCASE_SYMBOLS.length())));
hasLower = true;
} else if (!hasNumber) {
chars.add(NUMERIC_SYMBOLS.charAt(RandomUtils.nextInt(0, NUMERIC_SYMBOLS.length())));
hasNumber = true;
} else if (!hasSpecial) {
chars.add(SPECIAL_SYMBOLS.charAt(RandomUtils.nextInt(0, SPECIAL_SYMBOLS.length())));
hasSpecial = true;
} else {
chars.add(ALPHANUMERIC_AND_SPECIAL_SYMBOLS.charAt(RandomUtils.nextInt(0, ALPHANUMERIC_AND_SPECIAL_SYMBOLS.length())));
}
}
// Shuffle characters to mix up the first 4 characters
Collections.shuffle(chars);
return StringUtils.join(chars, "");
}
}
This question already has answers here:
How to generate a random alpha-numeric string
(46 answers)
Closed 9 years ago.
I am using String Builder from another answer, but I can't use anything but alpha/numeric, no whitespace, punctuation, etc. Can you explain how to limit the character set in this code? Also, how do I insure it is ALWAYS 30 characters long?
Random generator = new Random();
StringBuilder stringBuilder = new StringBuilder();
int Length = 30;
char tempChar ;
for (int i = 0; i < Length; i++){
tempChar = (char) (generator.nextInt(96) + 32);
stringBuilder.append(tempChar);
I have looked at most of the other answers, and can't figure out a solution to this.
Thanks. Don't yell at me if this is a duplicate. Most of the answers don't explain which part of the code controls how long the generated number is or where to adjust the character set.
I also tried stringBuilder.Replace(' ', '1'), which might have worked, but eclipse says there is no method for Replace for StringBuilder.
If you want to control the characterset and length take for example
public static String randomString(char[] characterSet, int length) {
Random random = new SecureRandom();
char[] result = new char[length];
for (int i = 0; i < result.length; i++) {
// picks a random index out of character set > random character
int randomCharIndex = random.nextInt(characterSet.length);
result[i] = characterSet[randomCharIndex];
}
return new String(result);
}
and combine with
char[] CHARSET_AZ_09 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
to specify the characterset.
It's not based on StringBuilder since you know the length and don't need all the overhead.
It allocates a char[] array of the correct size, then fills each cell in that array with a randomly chosen character from the input array.
more example use here: http://ideone.com/xvIZcd
Here's what I use:
public static String randomStringOfLength(int length) {
StringBuffer buffer = new StringBuffer();
while (buffer.length() < length) {
buffer.append(uuidString());
}
//this part controls the length of the returned string
return buffer.substring(0, length);
}
private static String uuidString() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
You may try this:
//piece
int i = 0;
while(i < length){
char temp =(char) (generator.nextInt(92)+32);
if(Character.isLetterOrDigit(temp))
{
stringBuilder.append(temp);
++i;
}
}
System.out.println(stringBuilder);
Should achieve your goal