我有一个包含 3 个元素的字符串:
- 3 位数代码(例如:SIN、ABD、SMS 等)
- 1 位数字代码类型(例如:1、2、3 等)
- 3 位数字(例如:500、123、345)
示例字符串:SIN1500、ABD2123、SMS3345 等。
我想生成一个唯一的 10 位字母数字和区分大小写的字符串(仅允许 0-9/a-z/A-Z),每个字符串提供超过 2^30(约 10 亿)个唯一组合。生成的代码必须具有特定的算法,以便我可以反转该过程。例如:
public static void main(String[] args) {
String test = "ABD2123";
String result = generateData(test);
System.out.println(generateOutput(test)); //for example, the output of this is: 1jS8g4GDn0
System.out.println(generateOutput(result)); //the output of this will be ABD2123 (the original string supplied)
}
我想问的是java中是否有任何想法/示例/库可以做到这一点?或者至少有关于我应该在谷歌上放置什么关键字的提示?
我尝试使用关键字 java checksum、rng、security、random number 等进行谷歌搜索,还尝试查看一些随机数解决方案(java SecureRandom、xorshift RNG、java.util.zip 的 checksum 等),但我似乎找不到?
谢谢!
编辑:
我对该程序的用例是生成某种唯一的优惠券编号以供特定客户使用。
提供的字符串将包含 3 位数的公司 ID 代码、1 位数的凭证类型代码以及 3 位数的凭证名称。我还尝试添加 3 个随机字母数字(因此最后的数字是 7 + 3 位数字 = 10 位数字)。这是我到目前为止所做的,但结果不是很好(只有大约10万个组合):
public static String in ="somerandomstrings";
public static String out="someotherrandomstrings";
public static String encrypt(String kata)
throws Exception {
String result="";
String ina=in;
String outa=out;
Random ran = new Random();
Integer modulus=in.length();
Integer offset= ((Integer.parseInt(Utils.convertDateToString(new Date(), "SS")))+ran.nextInt(60))/2%modulus;
result=ina.substring(offset, offset+1);
ina=ina+ina;
ina=ina.substring(offset, offset+modulus);
result=result+translate(kata, ina, outa);
return result;
}
编辑:
很抱歉我忘记添加“翻译”功能:
public static String translate(String kata,String seq1, String seq2){
String result="";
if(kata!=null&seq1!=null&seq2!=null){
String[] a=kata.split("");
for (int j = 1; j < a.length; j++) {
String b=a[j];
String[]seq1split=seq1.split("");
String[]seq2split=seq2.split("");
int hint=seq1.indexOf(b)+1;
String sq="";
if(seq1split.length>hint)
sq=seq1split[hint];
String sq1="";
if(seq2split.length>hint)
sq1=seq2split[hint];
b=b.replace(sq, sq1);
result=result+b;
}
}
return result;
}
编辑:
好吧,几天后我正在努力转换 @sarnold 提供的 Ruby 代码,这是我想出的代码:
public class Test {
static char START_A = "A".charAt(0);
static char START_a = "a".charAt(0);
static char START_0 = "0".charAt(0);
static int CODEMASK = ((1 << 28) - 1); //turn on lower 28 bits
static int RANDOMMASK = ((1 << 60) - 1) & ~ CODEMASK; //turn on upper 32 bits
public static void main(String[] args) {
String[] test = new String[]{
//"AAA0000", "SIN1500", "ABD2123", "SMS3345", "ZZZ9999",
//"ABD2123", "ABD2123", "ABD2123", "ABD2123", "ABD2123"
"ABD2123"
};
for(String t : test){
long c = compress(t);
long a = add_random(c);
String output = to_output(a);
long input = from_output(output);
String[] new_c_r = remove_random(input);
String u = uncompress(Long.valueOf(new_c_r[0]));
System.out.println("Original input: " + t);
System.out.println(" compressed: " + c);
System.out.println(" after adding random amount: " + a);
System.out.println(" *output: " + output);
System.out.println(" *input: " + input);
System.out.println(" random amount added: " + new_c_r[1]);
System.out.println(" after removing random amount: " + new_c_r[0]);
System.out.println(" uncompressed: " + u);
System.out.println("-----------------------------------------------------------------");
}
}
public static long compress(String line){ //7 character
char a = line.charAt(0);
char b = line.charAt(1);
char c = line.charAt(2);
char h = line.charAt(3);
char i = line.charAt(4);
char j = line.charAt(5);
char k = line.charAt(6);
long small_a = (long) a - START_A;
long small_b = (long) b - START_A;
long small_c = (long) c - START_A;
long letters = (small_a * 26 * 26) + (small_b * 26) + small_c;
long numbers = letters * 10000 + h * 1000 + i*100 + j*10 + k;
return numbers;
}
public static String uncompress(long number){
long k = number % 10;
number /= 10;
long j = number % 10;
number /= 10;
long i = number % 10;
number /= 10;
long h = number % 10;
number /= 10;
long small_c = number % 26;
number /= 26;
long small_b = number % 26;
number /= 26;
long small_a = number % 26;
number /= 26;
if (number != 0) throw new RuntimeException("input wasn't generated with compress()");
long a = small_a + START_A;
long b = small_b + START_A;
long c = small_c + START_A;
StringBuffer result = new StringBuffer();
result.append((char) a).append((char) b).append((char) c).append(h).append(i).append(j).append(k);
return result.toString();
}
public static long add_random(long number){
return (((long) (Math.random()* Math.pow(2, 31))) << 28) + number;
}
public static String[] remove_random(long number){
return new String[]{String.valueOf(number & CODEMASK), String.valueOf(number & RANDOMMASK)};
}
public static String to_output(long number){
List<Character> a = new ArrayList<Character>();
do{
a.add(transform_out(number % 62));
number /= 62;
}while(number > 0);
Collections.reverse(a);
StringBuffer result = new StringBuffer();
for(int i=0; i<a.size(); i++){
Character s = (Character) a.get(i);
result.append(s);
}
return result.toString();
}
public static long from_output(String string){
long num = 0;
for(char c : string.toCharArray()){
num *= 62;
num += transform_in(c);
}
return num;
}
public static char transform_out(long small){
long out;
if (small < 0 || small > 61){
throw new RuntimeException("small should be between 0 and 61, inclusive");
}
if(small < 26){
out = START_A + small;
}else if(small < 52){
out = START_a + (small-26);
}else{
out = START_0 + (small-52);
}
return (char) out;
}
public static long transform_in(char c){
if(!String.valueOf(c).matches("[a-zA-Z0-9]")){
throw new RuntimeException("char should be A-Z, a-z, or 0-9, inclusive");
}
long num = (long) c;
long out;
if(num >= START_A && num <= START_A+26) out = num-START_A;
else if(num >= START_a && num <= START_a+26) out = (num-START_a) + 26;
else if(num >= START_0 && num <= START_0+10) out = (num-START_0) + 52;
else throw new RuntimeException("Salah, bego!");
return out;
}}
但我似乎无法使这段代码正确,结果是这样的:
Original input: ABD2123
compressed: 345451
after adding random amount: 62781252268541291
*output: EnhZJdRFaj
*input: 62781252268541291
random amount added: 0
after removing random amount: 345451
uncompressed: ABI5451
您可能已经注意到“压缩”和“未压缩”字段没有显示相同的数量。 “随机添加量”字段也始终返回 0 值。 有没有人可以帮我看看这段代码哪里错了?
很抱歉,如果将此代码放入此线程中是错误的,我将创建另一个线程。
谢谢你, 优素福
最佳答案
你的要求很不明确。所以我将把我的答案限制为一般性:
有一些称为加密哈希函数的函数,可以将任意字节序列映射到“哈希”,其特性是任何两个相关输入给出相同输出的概率非常小。然而,加密哈希函数(根据设计)是不可逆的......根据设计。
从字符串的一个“空间”到另一个可逆的映射可以通过两种方式实现:
您可以生成任意字符串作为映射字符串,并使用哈希表等数据结构来存储正向和反向映射。
您可以使用加密哈希函数来生成映射的字符串,并使用哈希表等数据结构来存储反向映射。
您可以使用可逆函数在原始字符串和映射字符串之间进行转换。这存在一个问题,即映射可能很容易进行逆向工程。
后者的一个示例可能是将原始字符串转换为字节,然后对其进行 Base64 编码。或者更简单的是,您可以在输入字符串中的每个字符之间插入一个随机字符。 (显然,如果有足够多的例子,像这样的转换可以在几分钟内进行逆向工程。所以人们不得不怀疑这种方法的智慧。)
如果没有更好的要求,就不清楚您需要这些方法中的哪一种(如果有的话)。
关于java - 如何生成超过 2^30 个组合的随机唯一字符串。我也想扭转这个过程。这可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5293967/