车辆识别码VIN校验工具
参考 GB16735—2019《道路车辆 车辆识别代号(VIN)》
VIN组成
年份
校验位
代码
public class VinUtil {
/**
* 加权值. 因为第9位权重为0,所以原来是什么字符不影响结果,可以方便后面计算
*/
static int[] weightValue = {8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2};
/**
* VIN码各位数字的“对应值”.
*/
static Map<Character, Integer> vinValueMap = new HashMap<>();
/**
* 校验值.
*/
static char[] checkBit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X'};
/**
* VIN中不会包含 I、O、Q 三个英文字母.
*/
static String regex = "^[A-HJ-NPR-Z\\d]{8}[X\\d][A-HJ-NPR-Z\\d]{3}\\d{5}$";
static {
vinValueMap.put('0', 0);
vinValueMap.put('1', 1);
vinValueMap.put('2', 2);
vinValueMap.put('3', 3);
vinValueMap.put('4', 4);
vinValueMap.put('5', 5);
vinValueMap.put('6', 6);
vinValueMap.put('7', 7);
vinValueMap.put('8', 8);
vinValueMap.put('9', 9);
vinValueMap.put('A', 1);
vinValueMap.put('B', 2);
vinValueMap.put('C', 3);
vinValueMap.put('D', 4);
vinValueMap.put('E', 5);
vinValueMap.put('F', 6);
vinValueMap.put('G', 7);
vinValueMap.put('H', 8);
vinValueMap.put('J', 1);
vinValueMap.put('K', 2);
vinValueMap.put('M', 4);
vinValueMap.put('L', 3);
vinValueMap.put('N', 5);
vinValueMap.put('P', 7);
vinValueMap.put('R', 9);
vinValueMap.put('S', 2);
vinValueMap.put('T', 3);
vinValueMap.put('U', 4);
vinValueMap.put('V', 5);
vinValueMap.put('W', 6);
vinValueMap.put('X', 7);
vinValueMap.put('Y', 8);
vinValueMap.put('Z', 9);
}
/**
* 检验VIN格式.
*
* @param vin 车架号
* @return boolean
*/
public static boolean checkVin(String vin) {
if (vin == null) {
return false;
}
String upperVin = vin.toUpperCase();
// 排除长度不为17 字母O、I、Q
if (!Pattern.matches(regex, upperVin)) {
return false;
}
char[] vinArr = upperVin.toCharArray();
int amount = 0;
for (int i = 0; i < vinArr.length; i++) {
// VIN码从从第一位开始,码数字的对应值×该位的加权值,计算全部17位的乘积值相加
amount += vinValueMap.get(vinArr[i]) * weightValue[i];
}
// VIN码从从第一位开始,码数字的对应值×该位的加权值,计算全部17位的乘积值相加除以11,所得的余数,即为第九位校验值.
// 若余数为10,即为字母X
boolean bitFlag = checkBit[amount % 11] == vinArr[8];
// 第10位年份 不包含数字0、I、O、Q、U、Z
boolean flag = vinArr[9] == '0' || vinArr[9] == 'I' || vinArr[9] == 'O' || vinArr[9] == 'Q' || vinArr[9] == 'U'
|| vinArr[9] == 'Z';
return bitFlag && !flag;
}
}