作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在 400 万到 5000 万之间随机生成数百万个密码。问题是处理器处理它所需的时间。
我想知道是否有解决方案可以在几秒钟内生成大量密码(最多 1 分钟,5000 万次)。
我现在已经这样做了,但我花了超过 3 分钟的时间(配置非常好,我想在小配置上运行它)。
private final static String policy = "azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN1234567890";
private static List<String> names = new ArrayList<String>();
public static void main(String[] args) {
names.add("de");
init();
}
private static String generator(){
String password="";
int randomWithMathRandom = (int) ((Math.random() * ( - 6)) + 6);
for(var i=0;i<8;i++){
randomWithMathRandom = (int) ((Math.random() * ( - 6)) + 6);
password+= policy.charAt(randomWithMathRandom);
}
return password;
}
public static void init() {
for (int i = 0; i < 40000000; i++) {
names.add(generator());
}
}
顺便说一句,我不能拿现成的 list 。我认为最“昂贵”的时间浪费是输入列表。
最佳答案
将 5000 万个密码作为 String
存储在内存中可能会导致问题,因为堆栈或堆可能会溢出。从这个角度来看,我认为我们能做的最好的事情是生成一组密码,将它们存储在一个文件中,生成下一个密码块,将它们附加到文件中......直到创建所需数量的密码。我编写了一个小程序,它生成长度为 String
的随机 32
s。作为字母表,我使用了 '!'
(ASCII 值 33
)和 '~'
(ASCII 值 126
)之间的所有 ASCII 字符。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Random;
import java.util.concurrent.TimeUnit;
class Scratch {
private static final int MIN = '!';
private static final int MAX = '~';
private static final Random RANDOM = new Random();
public static void main(final String... args) throws IOException {
final Path passwordFile = Path.of("passwords.txt");
if (!Files.exists(passwordFile)) {
Files.createFile(passwordFile);
}
final DecimalFormat df = new DecimalFormat();
final DecimalFormatSymbols ds = df.getDecimalFormatSymbols();
ds.setGroupingSeparator('_');
df.setDecimalFormatSymbols(ds);
final int numberOfPasswordsToGenerate = 50_000_000;
final int chunkSize = 1_000_000;
final int passwordLength = 32;
int generated = 0;
int chunk = 0;
final long start = System.nanoTime();
while (generated < numberOfPasswordsToGenerate) {
final StringBuilder passwords = new StringBuilder();
for (
int index = chunk * chunkSize;
index < (chunk + 1) * chunkSize && index < numberOfPasswordsToGenerate;
++index) {
final StringBuilder password = new StringBuilder();
for (int character = 0; character < passwordLength; ++character) {
password.append(fetchRandomLetterFromAlphabet());
}
passwords.append(password.toString()).append(System.lineSeparator());
++generated;
if (generated % 500_000 == 0) {
System.out.printf(
"%s / %s%n",
df.format(generated),
df.format(numberOfPasswordsToGenerate));
}
}
++chunk;
Files.writeString(passwordFile, passwords.toString(), StandardOpenOption.APPEND);
}
final long consumed = System.nanoTime() - start;
System.out.printf("Done. Took %d seconds%n", TimeUnit.NANOSECONDS.toSeconds(consumed));
}
private static char fetchRandomLetterFromAlphabet() {
return (char) (RANDOM.nextInt(MAX - MIN + 1) + MIN);
}
}
在我的笔记本电脑上,该程序产生了良好的效果。它在大约 33 秒内完成,所有密码都存储在一个文件中。
password.txt
已经存在,则将附加内容。对我来说,运行一次后文件已经有 1.7 GB,所以请注意这一点。此外,生成的密码临时存储在
StringBuilder
中,这可能会带来安全风险,因为
StringBuilder
无法清除(即其内部存储器结构无法清零)。通过多线程运行密码生成可以进一步提高性能,但我将把它作为练习留给读者。
MIN
和
MAX
,定义一个新的静态字段
private static final char[] ALPHABET = "azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN1234567890".toCharArray();
并重新实现
fetchRandomLetterFromAlphabet
为:
private static char fetchRandomLetterFromAlphabet() {
return ALPHABET[RANDOM.nextInt(ALPHABET.length)];
}
我们可以使用以下代码片段在恒定时间内从文件中读回
n
-th(从
0
开始)密码:
final int n = ...;
final RandomAccessFile raf = new RandomAccessFile(passwordFile.toString(), "r");
final long start = System.nanoTime();
final byte[] bytes = new byte[passwordLength];
// byte-length of the first n passwords, including line breaks:
final int offset = (passwordLength + System.lineSeparator().toCharArray().length) * n;
raf.seek(offset); // skip the first n passwords
raf.read(bytes);
// reset to the beginning of the file, in case we want to read more passwords later:
raf.seek(0);
System.out.println(new String(bytes));
关于java - 在 Java 中生成数百万个随机字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66909107/
3-d 中的点由 (x,y,z) 定义。任意两点 (X,Y,Z) 和 (x,y,z) 之间的距离 d 为 d= Sqrt[(X-x)^2 + (Y-y)^2 + (Z-z)^2]。现在一个文件中有一百
我是一名优秀的程序员,十分优秀!