最近看到office2013在提示过期问题(升级win10后遗症),就想到模拟下office的激活码。~~
起初想到应该简单,最后越试越复杂。所以就记录下,毕竟花费了时间。
package test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class SerialNum {
//随机器,随机次数和符号等。
private static Random r = new Random();
//定义一些数字取值范围过滤,避免数字字母看起来混淆的问题,还有,避免暴力全遍历的问题。
private static List<Integer> numFilter = new ArrayList<>();
//定义一些字符取值范围过滤
private static List<Integer> charFilter = new ArrayList<>();
//初始化
static {
numFilter.add(0);
numFilter.add(1);
numFilter.add(5);
charFilter.add(97);// a
charFilter.add(65);
charFilter.add(101);// e
charFilter.add(69);
charFilter.add(105);// i
charFilter.add(73);
charFilter.add(108);// l
charFilter.add(76);
charFilter.add(111);// o
charFilter.add(79);
charFilter.add(115);// s
charFilter.add(83);
charFilter.add(117);// u
charFilter.add(85);
charFilter.add(122);// z
charFilter.add(90);
}
//main函数,批量生成多组
public static void main(String[] args) {
int i = 0;
while (i < 10) {
outSerialNum(5,5);
i++;
}
}
//获取一组序列,入参为序列有几组,每组长度为几
private static void outSerialNum(int group,int len) {
long start = System.currentTimeMillis();
StringBuilder s = new StringBuilder();
// 以随机串的分组数量为单位,获取每组的串
for (int i = 0; i < group; i++) {
// 传入每组串的长度
s.append(getRandomStr(len) + "-");
}
System.out.println(s.toString().substring(0, s.length()-1));
System.out.println("cost:" + (System.currentTimeMillis() - start));
}
// 获取一组长度为n的随机数字字母串
private static String getRandomStr(int len) {
StringBuilder sb = new StringBuilder();
String[] unit = new String[len];
// 随机出数字和字母出现的次数,保证数字和字母至少出现一次
int numCount = r.nextInt(len);
if (numCount == 0) {
numCount = 1;
}
int charCount = len - numCount;
// System.out.println("numCount=" + numCount + "; charCount=" +
// charCount);
// 获取二者中出现次数多的类型,优先随机插入数组
int max = numCount;
int flag = 0;// 表示数字类型
if (charCount > numCount) {
max = charCount;
flag = 1;// 字母
}
// 优先随机位置插入出现次数多的类型
for (int i = 0; i < max; i++) {
int f = r.nextInt(len);
if (flag == 0) {
unit[f] = String.valueOf(getNum());
} else {
unit[f] = String.valueOf(getChar());
}
}
// System.out.println("优先插入次数多的类型后:" + getArrayString(unit));
// 遍历数组,如果不为空,加入已经存在的字符串;为空,字符串填充另一种类型
for (String s : unit) {
if (null == s) {
// 与第一次插入采用相反的类型
if (flag == 0) {
sb.append(String.valueOf(getChar()));
} else {
sb.append(String.valueOf(getNum()));
}
} else {
sb.append(s);
}
}
return sb.toString();
}
private static int getNum() {
int n = r.nextInt(10);
return numFilter.contains(n) ? getNum() : n;// 不能在数字过滤器中
}
private static char getChar() {
int c = r.nextInt(26) + 97;
// 不能在字符过滤器中
return charFilter.contains(c) ? getChar() : (char) c;
}
}