Java 如何生成随机的字母数字字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate a random alpha-numeric string?
提问by Todd
I've been looking for a simpleJava 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).
我一直在寻找一种简单的Java 算法来生成伪随机字母数字字符串。在我的情况下,它将用作唯一的会话/密钥标识符,“可能”在500K+
生成时是唯一的(我的需求实际上并不需要更复杂的东西)。
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"
.
理想情况下,我将能够根据我的独特性需求指定长度。例如,生成的长度为 12 的字符串可能类似于"AEYGF7K0DM1X"
.
采纳答案by erickson
Algorithm
算法
To generate a random string, concatenate characters drawn randomly from the set of acceptable symbols until the string reaches the desired length.
要生成随机字符串,请连接从一组可接受的符号中随机抽取的字符,直到字符串达到所需的长度。
Implementation
执行
Here's some fairly simple and very flexible code for generating random identifiers. Read the information that followsfor important application notes.
这是一些用于生成随机标识符的相当简单且非常灵活的代码。阅读以下重要应用笔记的信息。
public class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}
Usage examples
使用示例
Create an insecure generator for 8-character identifiers:
为 8 个字符的标识符创建一个不安全的生成器:
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
Create a secure generator for session identifiers:
为会话标识符创建一个安全的生成器:
RandomString session = new RandomString();
Create a generator with easy-to-read codes for printing. The strings are longer than full alphanumeric strings to compensate for using fewer symbols:
创建一个带有易于阅读的打印代码的生成器。字符串比完整的字母数字字符串长以补偿使用较少的符号:
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
Use as session identifiers
用作会话标识符
Generating session identifiers that are likely to be unique is not good enough, or you could just use a simple counter. Attackers hiHyman sessions when predictable identifiers are used.
生成可能是唯一的会话标识符还不够好,或者您可以只使用一个简单的计数器。当使用可预测的标识符时,攻击者会劫持会话。
There is tension between length and security. Shorter identifiers are easier to guess, because there are fewer possibilities. But longer identifiers consume more storage and bandwidth. A larger set of symbols helps, but might cause encoding problems if identifiers are included in URLs or re-entered by hand.
长度和安全性之间存在紧张关系。较短的标识符更容易猜测,因为可能性较少。但是更长的标识符消耗更多的存储和带宽。更大的符号集会有所帮助,但如果标识符包含在 URL 中或手动重新输入,则可能会导致编码问题。
The underlying source of randomness, or entropy, for session identifiers should come from a random number generator designed for cryptography. However, initializing these generators can sometimes be computationally expensive or slow, so effort should be made to re-use them when possible.
会话标识符的随机性或熵的潜在来源应该来自为密码学设计的随机数生成器。然而,初始化这些生成器有时会在计算上很昂贵或很慢,所以应该尽可能地重用它们。
Use as object identifiers
用作对象标识符
Not every application requires security. Random assignment can be an efficient way for multiple entities to generate identifiers in a shared space without any coordination or partitioning. Coordination can be slow, especially in a clustered or distributed environment, and splitting up a space causes problems when entities end up with shares that are too small or too big.
并非每个应用程序都需要安全性。随机分配可以是多个实体在共享空间中生成标识符的有效方式,无需任何协调或分区。协调可能很慢,尤其是在集群或分布式环境中,当实体最终共享太小或太大时,拆分空间会导致问题。
Identifiers generated without taking measures to make them unpredictable should be protected by other means if an attacker might be able to view and manipulate them, as happens in most web applications. There should be a separate authorization system that protects objects whose identifier can be guessed by an attacker without access permission.
如果攻击者可能能够查看和操纵标识符,则在未采取措施使其不可预测的情况下生成的标识符应通过其他方式进行保护,就像在大多数 Web 应用程序中发生的那样。应该有一个单独的授权系统来保护其标识符可以在没有访问权限的情况下被攻击者猜到的对象。
Care must be also be taken to use identifiers that are long enough to make collisions unlikely given the anticipated total number of identifiers. This is referred to as "the birthday paradox." The probability of a collision,p, is approximately n2/(2qx), where nis the number of identifiers actually generated, qis the number of distinct symbols in the alphabet, and xis the length of the identifiers. This should be a very small number, like 2‑50or less.
考虑到预期的标识符总数,还必须注意使用足够长的标识符,以避免发生冲突。这被称为“生日悖论”。碰撞概率p大约为 n 2/(2q x),其中n是实际生成的标识符的数量,q是字母表中不同符号的数量,x是标识符的长度。这应该是一个非常小的数字,例如 2 ‑50或更少。
Working this out shows that the chance of collision among 500k 15-character identifiers is about 2‑52, which is probably less likely than undetected errors from cosmic rays, etc.
计算出这个结果表明 500k 15 个字符的标识符之间发生冲突的几率约为 2 ‑52,这可能比宇宙射线等未检测到的错误的可能性要小。
Comparison with UUIDs
与 UUID 的比较
According to their specification, UUIDsare not designed to be unpredictable, and should notbe used as session identifiers.
根据他们的规范,UUID并非设计为不可预测的,不应用作会话标识符。
UUIDs in their standard format take a lot of space: 36 characters for only 122 bits of entropy. (Not all bits of a "random" UUID are selected randomly.) A randomly chosen alphanumeric string packs more entropy in just 21 characters.
标准格式的 UUID 占用大量空间:36 个字符仅用于 122 位熵。(并非“随机”UUID 的所有位都是随机选择的。)随机选择的字母数字字符串仅在 21 个字符中包含更多熵。
UUIDs are not flexible; they have a standardized structure and layout. This is their chief virtue as well as their main weakness. When collaborating with an outside party, the standardization offered by UUIDs may be helpful. For purely internal use, they can be inefficient.
UUID 不灵活;它们具有标准化的结构和布局。这是他们的主要美德,也是他们的主要弱点。与外部合作时,UUID 提供的标准化可能会有所帮助。对于纯粹的内部使用,它们可能效率低下。
回答by Apocalisp
Here it is in Java:
这是在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
回答by Steve McLeod
Java supplies a way of doing this directly. If you don't want the dashes, they are easy to strip out. Just use uuid.replace("-", "")
Java 提供了一种直接执行此操作的方法。如果你不想要破折号,它们很容易去掉。只需使用uuid.replace("-", "")
import java.util.UUID;
public class randomStringGenerator {
public static void main(String[] args) {
System.out.println(generateString());
}
public static String generateString() {
String uuid = UUID.randomUUID().toString();
return "uuid = " + uuid;
}
}
Output:
输出:
uuid = 2d7428a6-b58c-4008-8575-f05549f16316
回答by Todd
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;
int size = 16;
/* Seems like we should be able to generate 500K tokens
* without a duplicate
*/
for (int i=0; i<500000; i++){
token = Utility.generateUniqueToken(size);
if (token.length() != size * 2){
fail("Incorrect length");
} else if (set.contains(token)) {
fail("Duplicate token generated");
} else{
set.add(token);
}
}
}
回答by cmsherratt
If you're happy to use Apache classes, you could use org.apache.commons.text.RandomStringGenerator
(commons-text).
如果您乐于使用 Apache 类,则可以使用org.apache.commons.text.RandomStringGenerator
(commons-text)。
Example:
例子:
RandomStringGenerator randomStringGenerator =
new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
.build();
randomStringGenerator.generate(12); // toUpperCase() if you want
Since commons-lang 3.6, RandomStringUtils
is deprecated.
由于 commons-lang 3.6,RandomStringUtils
已弃用。
回答by maxp
static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static SecureRandom rnd = new SecureRandom();
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();
}
回答by maxp
I have developed an application to develop an auto generated alphanumberic string for my project. In this string, the first three chars are alphabetical and the next seven are integers.
我开发了一个应用程序来为我的项目开发一个自动生成的字母数字字符串。在这个字符串中,前三个字符是字母,接下来的七个是整数。
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);
}
}
回答by maxp
In one line:
在一行中:
Long.toHexString(Double.doubleToLongBits(Math.random()));
http://mynotes.wordpress.com/2009/07/23/java-generating-random-string/
http://mynotes.wordpress.com/2009/07/23/java-generating-random-string/
回答by dfa
using Dollarshould be simple as:
使用Dollar应该很简单:
// "0123456789" + "ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();
String randomString(int length) {
return $(validCharacters).shuffle().slice(length).toString();
}
@Test
public void buildFiveRandomStrings() {
for (int i : $(5)) {
System.out.println(randomString(12));
}
}
it outputs something like that:
它输出类似的东西:
DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7
回答by Suganya
import java.util.*;
import javax.swing.*;
public class alphanumeric{
public static void main(String args[]){
String nval,lenval;
int n,len;
nval=JOptionPane.showInputDialog("Enter number of codes you require : ");
n=Integer.parseInt(nval);
lenval=JOptionPane.showInputDialog("Enter code length you require : ");
len=Integer.parseInt(lenval);
find(n,len);
}
public static void find(int n,int length) {
String str1="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuilder sb=new StringBuilder(length);
Random r = new Random();
System.out.println("\n\t Unique codes are \n\n");
for(int i=0;i<n;i++){
for(int j=0;j<length;j++){
sb.append(str1.charAt(r.nextInt(str1.length())));
}
System.out.println(" "+sb.toString());
sb.delete(0,length);
}
}
}