JAVA验证身份证号码校验码是否正确

JAVA验证身份证号码校验码是否正确


设计思路

  • 1、将身份证号码前17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
  • 2、将这17位数字和系数相乘的结果相加
  • 3、用加出来和除以11,看余数是多少;
  • 4、余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2

代码实现思路

  • 1、使用 Scanner工具类获取输入的字符串
  • 2、将输入的字符串转换为字符数组使用toCharArray()方法),字符类型可直接参与数学运算
  • 3、查询ASCII码表可知数字0在表中对应的编码为48,一次类推,故每个char字符需要减去48,才能代表其实际数值;
  • 4、创建一个Map集合,用于存放计算后的余数与校验码对应的值
  • 5、根据计算出的余数获取Map集合的校验码与输入的校验码进行对比,可得出输入的身份证号是否合法;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
 * @author 二师兄想吃肉
 * @version 1.0
 * @date 2020/12/23 13:55
 */
public class Demo {
    public static void main(String[] args) {
        // 创建键盘输入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("---请输入前18位身份证号码---");
        // 获取键盘输入的值
        String idNo = sc.next();
        // 将输入的字符串转换为字符数组,方便计算
        char[] chars = idNo.toCharArray();
        // 将字符数组每个字符减去 48 为真实数值(可查阅ASCII表)
        int sum =
            (chars[0] - 48 ) * 7 +
            (chars[1] - 48 ) * 9 +
            (chars[2] - 48 ) * 10 +
            (chars[3] - 48 ) * 5 +
            (chars[4] - 48 ) * 8 +
            (chars[5] - 48 ) * 4 +
            (chars[6] - 48 ) * 2 +
            (chars[7] - 48 ) * 1 +
            (chars[8] - 48 ) * 6 +
            (chars[9] - 48 ) * 3 +
            (chars[10] - 48 ) * 7 +
            (chars[11] - 48 ) * 9 +
            (chars[12] - 48 ) * 10 +
            (chars[13] - 48 ) * 5 +
            (chars[14] - 48 ) * 8 +
            (chars[15] - 48 ) * 4 +
            (chars[16] - 48 ) * 2;
        // 取模运算
        int mod = sum % 11;

        // 采用键值对的形式存储余数与校验码的对应关系
        Map<Integer,Character> map = new HashMap<>(11);
        map.put(0,'1');
        map.put(1,'0');
        map.put(2,'X');
        map.put(3,'9');
        map.put(4,'8');
        map.put(5,'7');
        map.put(6,'6');
        map.put(7,'5');
        map.put(8,'4');
        map.put(9,'3');
        map.put(10,'2');

        // 根据计算出的余数获取到校验码
        Character character = map.get(mod);

        // 将输入的校验码与获取到的校验码进行比较
        if (chars[17] == character) {
            System.out.println("身份证号码正确!");
        } else {
            System.out.println("身份证号码错误!");
            System.out.println("最后一位校验码应为:" + character);
        }

    }
}

以上为校验码判断的核心代码,未进行异常处理
以下为完善后的代码
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 二师兄想吃肉
 * @version 1.0
 * @Title: 身份证校验码
 * @Description: 校验身份证号码和生成身份证校验码
 * @date 2020/12/17 11:55
 */
public class Demo01 {

    public static void main(String[] args) throws Exception {
        randomMethod();
    }

    /**
     * 随机执行校验身份证号码方法、生成身份证校验码方法、打印矩形
     * @throws Exception
     */
    public static void randomMethod() throws Exception{
        while(true){
            int i = new Random().nextInt(15);
            if(i % 3 == 0){
                checkIdNo();
            }else if(i % 3 == 1){
                makeCheckCode();
            }else if(i % 3 == 2){
                System.out.println("\n---你看↓↓↓突然就想打印个矩形---");
                for (int width = 0; width < 5; width++) {
                    for (int height = 0; height < 25; height++) {
                        Thread.sleep(50);
                        System.out.print("*");
                    }
                    System.out.println();
                }
            }
        }
    }

    /**
     * 校验输入的18位身份证号码输入是否正确
     * @throws Exception
     */
    public static void checkIdNo() throws Exception {
        System.out.println();
        Scanner sc = new Scanner(System.in);
        System.out.println("---请输入18位身份证号码---");
        if(sc.hasNext()){
            String str = sc.next();
            int length = str.length();
            if(length == 18){
                char aChar = str.charAt(17);
                if((aChar < 48 || aChar > 57) && (aChar != 88 && aChar != 120)){
                    System.out.println("你第" + length + "位输错了。");
                    return;
                }
                Character code = map.get(checkTwo(checkOne(str)));
                if(code != 'E'){
                    String result = code.equals(str.charAt(17)) || Character.valueOf((char)(code + 32)).equals(str.charAt(17))
                            ? "身份证号码校验通过!" : "身份证号码校验失败,你重试吧~";
                    System.out.println(result);
                }else{
                    System.out.println("输入不合法,请输入有效数据!");
                }
            }else if((length > 14 && length <= 17) || (length > 18 && length <= 21)){
                System.out.println("你数数是不是位数不对,我还不能告诉你校验码~");
            }else if("我是憨憨".equals(str)){
                System.out.println("这话说的漂亮啊弟弟");
            }else {
                System.out.println("能不能好好输,重来!");
            }
        }else{
            throw new Exception("输入有误,请重新输入!");
        }
    }

    /**
     * 根据前17位身份证号码,生成最后一位校验码
     */
    public static void makeCheckCode() throws Exception {
        System.out.println();
        Scanner sc = new Scanner(System.in);
        System.out.println("---请输入前17位身份证号码---");
        if(sc.hasNext()) {
            String str = sc.next();
            int length = str.length();
            if(length == 17){
                char[] chars = checkOne(str);
                int i = checkTwo(chars);
                Character code = map.get(i);
                if(code != 'E'){
                    System.out.println("最后一位校验码为:" + code + "\n"
                            + "18位身份证号码为:" + (str + code));
                }else{
                    System.out.println("输入不合法,请输入有效数据!");
                }
            }else if((length > 13 && length <= 16) || (length > 17 && length <= 20)){
                System.out.println("内容对不对我不知道,但是你输得位数不太对~");
            }else if("我是憨憨".equals(str)){
                System.out.println("这话说的漂亮啊弟弟");
            }else {
                System.out.println("能不能好好输,重来!");
            }
        }else{
            throw new Exception("输入有误,请重新输入!");
        }
    }

    /**
     * 判断输入的身份证号长度与字符输入是否正确
     * @param idNo
     * @return 字符数组
     * @throws Exception
     */
    public static char[] checkOne(String idNo) throws Exception {
        //如果参数字符串长度小于17,直接返回空字符数组,避免接下来字符串转换字符数组出现异常
        //如果参数字符串长度大于18,直接返回空字符数组,属于不合法输入
        if(idNo.length() < 17 || idNo.length() > 18){
            return new char[]{};
        }
        //字符串转为字符数组
        char[] chars = idNo.substring(0,17).toCharArray();
        //首先判断字符串长度是否符合规则
        if(chars.length == 17){
            //判断每个字符是否符合规则
            int num = 0;
            for (int i = 0; i < chars.length; i++) {
                int aChar = chars[i] += 0;
                if(i < 17 && (aChar < 48 || aChar > 57)){
//                throw new Exception("你第" + (i + 1) + "位输错了,你得按规矩来。");
                    System.out.println("你第" + (i + 1) + "位输错了,你得按规矩来。");
                    num++;
                }
            }
            //如果身份证号输入字符存在不合法字符,返回空字符数组。
            if (num != 0) {
                return new char[]{};
            }
            return chars;
        }else{
            System.out.println("你长度不对劲,你得重新输一遍。");
            return new char[]{};
        }
    }

    /**
     * 根据输入的前17位身份证号码生成最后一位校验码
     * @param chars
     * @return map的键
     * @throws Exception
     */
    public static int checkTwo(char[] chars) throws Exception{
        // 将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 ;
        // 将这17位数字和系数相乘的结果相加;
        if(chars.length == 17){
            int sum =
                (chars[0] - 48 ) * 7 +
                (chars[1] - 48 ) * 9 +
                (chars[2] - 48 ) * 10 +
                (chars[3] - 48 ) * 5 +
                (chars[4] - 48 ) * 8 +
                (chars[5] - 48 ) * 4 +
                (chars[6] - 48 ) * 2 +
                (chars[7] - 48 ) * 1 +
                (chars[8] - 48 ) * 6 +
                (chars[9] - 48 ) * 3 +
                (chars[10] - 48 ) * 7 +
                (chars[11] - 48 ) * 9 +
                (chars[12] - 48 ) * 10 +
                (chars[13] - 48 ) * 5 +
                (chars[14] - 48 ) * 8 +
                (chars[15] - 48 ) * 4 +
                (chars[16] - 48 ) * 2;
            // 用加出来和除以11,看余数是多少;
            int mod = sum % 11;
            return mod;
        }
        return -1;
    }

    //用于存放校验码的键值map
    static Map<Integer,Character> map;

    //类初始化时向map集合添加数据
    static {
        //余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2
        //尖括号添加泛型保证一定的向下兼容性
        map = new ConcurrentHashMap</*Integer,Character*/>(11);
        map.put(0,'1');
        map.put(1,'0');
        map.put(2,'X');
        map.put(3,'9');
        map.put(4,'8');
        map.put(5,'7');
        map.put(6,'6');
        map.put(7,'5');
        map.put(8,'4');
        map.put(9,'3');
        map.put(10,'2');
        //作为异常处理的错误码
        map.put(-1,'E');
    }

}

你可能感兴趣的:(经验分享,java,身份证校验码)