分享一个自己写的UUID转25位SN编码的算法
需求
需要生成用户输入的SN编码,该编码需要满足3个特征:
1)唯一编码,不重复
2)为了方便输入,仅包含大写和数字,避免出现混淆的字符,例如0和O,8和B
3)尽可能的短小
方案
1)满足条件1的方案,可以考虑采用UUID编码
2)混淆的字符,可以考虑采用字典编码的方式,将混淆的字符从字典里剔除
3)尽可能的短小,我们可以将其它字符考虑进来,这样增加G-Z字符并能压缩长度
实现
我们建立一个5bit的的字典,共32个字符,用于压缩信息信息,这样每个字符可以多处理1bit,我们只需要把重新划分即可。我们建立这个32字符字典,把0和O,8和B这两个容易弄混的数字干掉:
12345679ACDEFGHIJKLMNPQRSTUVWXYZ
然后重新按bit映射实现信息压缩,将4位一组的信息重新划分,并在字典里找到映射信息,如下图:
这样每5个字符我们就可以压缩1字符。但是由于4*32%5=3,该3位为UUID的随机位,考虑不参与计算。当然也可以添加进来,形成26位SN,下面是25位SN的算法:
import java.util.UUID;
import org.apache.commons.lang3.RegExUtils;
/**
* @author Jim
*/
public class UUIDUtil {
private static final char[] SN_CHAR_DICT = "12345679ACDEFGHIJKLMNPQRSTUVWXYZ".toCharArray(); //5位SN字典,把0和O,8和B这两个容易弄混的数字干掉
/**
* 使用字典将UUID转25位SN
* @return
*/
public static String randomSN() {
String uuidStr = RegExUtils.replaceAll(UUID.randomUUID().toString(), "-", "");
StringBuilder binBuilder = new StringBuilder();
for(byte numbyte: uuidStr.getBytes()) {
String binStr = Integer.toString(numbyte, 2);
binBuilder.append(("0000" + binStr).substring(binStr.length()));
}
StringBuilder snBuilder = new StringBuilder();
for(int i = 0; i < 25; i ++) {
snBuilder.append(SN_CHAR_DICT[Integer.parseInt(binBuilder.substring(i*5, i*5+5), 2)]);
}//最后3位丢弃,形成25位SN
return snBuilder.toString();
}
}
该算法适合手输或印刷SN编码。如果要采用URL来传递参数,也可以采用同样的算法,大小写相关字符将UUID压缩到22位,有兴趣的可以自己试试