import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class GenSerial {
private static final String Base32Alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
/**
* 生成新的序列號 <br>
* <p>生成規則:45位的數 (二進制)<br>
* 標識位 + 數據位 + 校驗位 <br>
* 然後將55位的數映射到用 ABCDEFGHJKLMNPQRSTUVWXYZ23456789 表示的序列號,要映射到32個字符中就是每5位代表一個字符(2^5=32),
* 所有生成的序列號是 45/5=9位。
*
* @param codeLen code長度
* @param flag 標識
* @param flagBitLen 標識長度
* @param checkBitLen 校驗位長度
* @return
*/
public static String generateNewCode(int codeLen, int flag, int flagBitLen, int checkBitLen) {
Long ret = 0L; // 長整形ID
Random random = new Random();
int checkModData = 1<<checkBitLen;
int totalBitLen = codeLen*5;
int dataBitLen = totalBitLen - checkBitLen - flagBitLen;
long randData = (long)(1 + (1L<<dataBitLen - 1) * random.nextDouble());
if(flagBitLen > 0){
flag = flag & ((1<<flagBitLen) - 1); //防止越位,若16位標識則是 0xffff
ret += (long)flag << (totalBitLen - flagBitLen); //高位標誌位
}
ret += randData << checkBitLen; // 中位數據位
long checkNum = (ret >> checkBitLen) % checkModData; //低位校驗位
ret += checkNum; // 1 - 7位 校驗位
return convertToBase32SerialCode(ret, codeLen);
}
public static String generateNewCode(int flag, int flagBitLen) {
return generateNewCode(9, flag, flagBitLen, 7); //生成碼9位,活動id 16位
}
public static String generateNewCode(int flag) {
int flagBitLen = 0;
if(flag == 0){
flagBitLen = 0;
}else{
flagBitLen = Integer.toBinaryString(flag).length();
}
return generateNewCode(9, flag, flagBitLen, 7); //生成碼9位
}
public static String generateNewCode() {
return generateNewCode(9, 0, 0, 7); //生成碼9位
}
/**
*
* @param historyCodeSet 歷史生成的序列號 集合
* @param number
* @param codeLen
* @param flag
* @param flagBitLen
* @param checkBitLen
* @return
*/
public static Set<String> generateCodes(Set<String> historyCodeSet, int number, int codeLen, int flag, int flagBitLen, int checkBitLen){
Set<String> generatedCodes = new HashSet<String>(number*4/3+1);
if(historyCodeSet == null){
historyCodeSet = new HashSet<String>(0);
}
while(generatedCodes.size()<number){
String code = generateNewCode(codeLen, flag, flagBitLen, checkBitLen);
if(!historyCodeSet.contains(code)){
generatedCodes.add(code);
}
}
return generatedCodes;
}
/**
*
* @param historyCodeSet
* @param number
* @return
*/
public static Set<String> generateCodes(Set<String> historyCodeSet, int number, int codeLen){
return generateCodes(historyCodeSet, number, codeLen, 0, 0, 7);
}
/**
*
* @param historyCodeSet
* @param number
* @return
*/
public static Set<String> generateCodes(Set<String> historyCodeSet, int number){
return generateCodes(historyCodeSet, number, 9, 0, 0, 7);
}
/**
* 將隨機數轉換成BASE32編碼 序列碼
*
* @return
*/
private static String convertToBase32SerialCode(long longRandValue, int codeLen) {
StringBuffer codeSerial = new StringBuffer(16);
long tmpRandValue = longRandValue;
for (int i = 0; i < codeLen; i++) {
int code = (int) (tmpRandValue & 0x1F);
char convertCode = Base32Alphabet.charAt(code);
codeSerial.append(convertCode);
tmpRandValue = tmpRandValue >> 5;
}
return codeSerial.reverse().toString();
}
/**
* 將兌換碼序列字符轉化成數字。
*
* @return
*/
private static int convertBase32CharToNum(char ch) {
int index = Base32Alphabet.indexOf(ch);
return index;
}
/**
* 將序列號轉成長整數
*
* @return
*/
public static long convertBase32CharToNum(String serialCode) {
long id = 0;
for (int i = 0; i < serialCode.length(); i++) {
int originNum = convertBase32CharToNum(serialCode.charAt(i));
if(originNum == -1){
return 0;
}
id = id << 5;
id += originNum;
}
return id;
}
/**
* 校驗序列號是否合法
*
* @param code
* @return
*/
public static boolean checkCodeValid(String code, int checkBitLen) {
long id = 0;
int checkModData = 1<<checkBitLen;
for (int i = 0; i < code.length(); ++i) {
long originNum = convertBase32CharToNum(code.charAt(i));
if (originNum >= 32)
return false; // 字符非法
id = id<<5;
id += originNum;
}
long data = id >> checkBitLen;
long checkNum = id & (checkModData-1); // 最後7位是校驗碼
if (data % checkModData == checkNum)
return true;
return false;
}
public static boolean checkCodeValid(String code) {
if(code == null || code.length() == 0){
return false;
}
return checkCodeValid(code, 7);
}
/**
* 從序列號提取標識
*
* @param code 序列號
* @param flagBitLen 標識位長度
* @return
*/
public static Long getFlagFromCode(String code, int flagBitLen){
long id = convertBase32CharToNum(code);
return id >> (code.length()*5-flagBitLen);
}
public static void main(String[] args) {
System.out.println(checkCodeValid("ARXX2BWTE"));
long sTime = System.currentTimeMillis();
long eTime = 0L;
Set<String> codes = generateCodes(null, 7000000, 9, 0, 0, 7);
eTime = System.currentTimeMillis();
System.out.println("耗時 " + (eTime-sTime)/1000 + "秒");
sTime = eTime;
Set<String> codes2 = generateCodes(codes, 2000000, 9, 0, 0, 7);
codes2.size();
eTime = System.currentTimeMillis();
System.out.println("耗時 " + (eTime-sTime)/1000 + "秒");
String code = generateNewCode(1,10);
System.out.println("序列號: "+code);
boolean checkRs = checkCodeValid(code);
System.out.println("序列號" + code + "是否合法:" + checkRs);
long acId = getFlagFromCode(code,10);
System.out.println("標識: " + acId);
long numCode = convertBase32CharToNum(code);
System.out.println("數字序列號 " + numCode);
}
}
java生成兌換碼禮包碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.