频道栏目
首页 > 资讯 > Java > 正文

Java:身份证号的校验与生成

17-08-11        来源:[db:作者]  
收藏   我要投稿

Java:身份证号码严格校验,与生成

身份证前6位地区码

缘由:现在好多手机端应用,借助互联网实名认证或安全等口号,向用户索取更多的信息,比如绑定身份证。
根据网上关于身份证的百科,我写了一个我认为最严格的校验身份证号码,以及随机生成身份证号的java代码
(网上有很多身份证号检验,随机生成身份证号 的网站)

校验身份证代码

package identity.card;

import java.io.FileReader;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Scanner;
import java.util.Set;
/*
 * 身份证组成:2(省级)2(地级市)2(县级)8(出生:年月日)3(派出所代码)1(校验码)
 * 其中第17位:奇数=男,偶数=女
    加权码wi:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
    // 获取校验码:将身份证 (前17位*加权码)所得总和 再对11取余=校验码索引
    校验码(18): 1 0 X 9 8 7 6 5 4 3 2 

 */

public class IdentityCard {
    private static Scanner sc;

    public static void main(String[] args) {
        try {
            idCard();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void idCard() throws Exception {
        sc = new Scanner(System.in);
        System.out.println("请输入需要校验的身份证号:");
        String id = sc.next();// id:身份证号
        // 正则初步:校验身份证
        // 日期: ((0[1-9])|(1[0-2])):匹配"01-12"月
        // (([0-2][1-9])|10|20|30|31):匹配"01-31"天
        String regID = "[1-9]\\d{5}[1-9]\\d{3}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9xX]";
        if (!id.matches(regID)) {
            System.out.println("正则不匹配");
            return;
        }

        // 进一步:年月日校验
        int year = Integer.parseInt(id.substring(6, 10));
        int month = Integer.parseInt(id.substring(10, 12));
        int day = Integer.parseInt(id.substring(12, 14));
        System.out.println(year + "," + month + "," + day);
        if (day > 28 && !isDate(year, month, day)) {
            System.out.println("日期规则不对");
            return;
        }

        // 再进一步:检验最后一位校验码
        // 获取加权码wi:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
        int[] wi = new int[17];
        for (int i = 1; i < 18; i++) {
            // 获取加权数字
            int winum = (int) (Math.pow(2, i) % 11);
            // 将加权数反向存入数组
            wi[wi.length - i] = winum;
        }

        // 获取加权后的总和
        int sum = 0;
        id = id.trim();// 去空格
        for (int i = 0; i < wi.length; i++) {
            // 获取身份证前17位的每一位,转换为数字
            int j = Integer.parseInt(id.substring(i, i + 1));
            // 获取加权后所得的和
            sum += (j * wi[i]);
        }

        // 匹配校验码
        String Ai = "10x987654342";
        // 获取验证码索引:
        int index = sum % 11;
        // 比较输入身份证与所得校验码比较(忽略大小写)
        if (id.substring(17).equalsIgnoreCase(Ai.substring(index, index + 1))) {
            // 判断男女
            System.out.println(((Integer.parseInt(id.substring(16, 17)) % 2) == 0) ? "女生" : "男生");
        } else {
            System.out.println("校验不成功");
            return;
        }

        // isAreacode(id);//按行读取地区编码文档,匹配法

        // 最后一步地区码校验.properties集合方法
        Properties p = new Properties();
        // 加载地区码配置文件
        p.load(new FileReader("ID=Zone.txt"));
        Set<>> entrySet = p.entrySet();
        boolean flag2 = true;

        for (Entry entry : entrySet) {
            String key = (String) entry.getKey();
            // 匹配身份证所属区域
            if (id.substring(0, 6).equals(key)) {
                System.out.println(entry.getValue());
                flag2 = false;
                break;
            }
        }
        if (flag2)
            System.out.println("没有此地区:你的身份证有误");
        else
            System.out.println("读取结束");
    }

    // 进一步日期判断
    public static boolean isDate(int year, int month, int day) {// day=29|30|31
        // 日期口诀: 一三五七八十腊(12月),三十一天永不差;平年二月二十八;闰年二月把一加 ;四六九冬(11月)三十日
        // 闰年:四年一闰,百年不闰,四百年再闰.
        if (month == 2) {// 当月份=2时
            if (day == 29 && (year % 4 == 0 && year % 100 != 0 | year % 400 == 0))
                return true;
            // 是2月非闰年
            return false;
        }
        // 天数是31天,月份却是:4|6|9|11
        if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11))
            return false;
        // 其它正常情况
        return true;
    }
}

身份证随机生成方法

public static void diyIdCard() {
        // 获取6为地区码
        Random ra = new Random();
        // 以生成的随机数=循环的次数:来获取随机地区码
        int num = ra.nextInt(3465) + 1;
        int count = 0;// 循环次数
        String str1 = "";// 六位地区码
        String zone = "";
        Properties p = new Properties();
        // 加载地区码配置文件
        try {
            p.load(new FileReader("ID=Zone.txt"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        Set<>> entrySet = p.entrySet();

        // 遍历地区码文件
        for (Entry entry : entrySet) {
            count++;
            // 匹配身份证所属区域
            if (num == count) {
                str1 = (String) entry.getKey();// 地区码
                zone = (String) entry.getValue();// 获取地区
                break;
            }
        }
        System.out.println(str1 + ":" + zone);

        // 获取年份
        Calendar cal = Calendar.getInstance();
        // 获取现在年份
        int year = cal.get(cal.YEAR);
        // 获取150年前到现在的年份
        String str2 = Integer.toString(year - ra.nextInt(151));

        // 获取月份
        String str3 = "";
        int month = ra.nextInt(12) + 1;
        if (month < 10) {
            str3 = "0" + Integer.toString(month);
        } else {
            str3 = Integer.toString(month);
        }

        // 获取天
        String str4 = "";
        int day = ra.nextInt(31) + 1;
        if (day < 10) {
            str4 = "0" + Integer.toString(day);
        } else {
            str4 = Integer.toString(day);
        }

        // 判断生成日期是否符合规则
        if (day > 28 && !isDate(year, month, day)) {
            System.out.println(year + ":" + month + ":" + day);
            // 重新赋值天数
            str4 = Integer.toString(day - 3);
            System.out.println("日期-天:" + str4);
        }

        // 获取3位随机数
        String str5 = "";
        int ran3 = ra.nextInt(1000);
        if (ran3 < 10) {
            str5 = "00" + Integer.toString(ran3);
        } else if (ran3 < 100) {
            str5 = "0" + Integer.toString(ran3);
        } else {
            str5 = Integer.toString(ran3);

        }

        // 获取校验码
        // 获取加权后的总和
        String id = str1 + str2 + str3 + str4 + str5;// 前17位ID
        // 获取加权码wi:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
        int[] wi = new int[17];
        for (int i = 1; i < 18; i++) {
            // 获取加权数字
            int winum = (int) (Math.pow(2, i) % 11);
            // 将加权数反向存入数组
            wi[wi.length - i] = winum;
        }
        // 获取加权后的总和
        int sum = 0;
        for (int i = 0; i < wi.length; i++) {
            // 获取身份证前17位的每一位,转换为数字
            int j = Integer.parseInt(id.substring(i, i + 1));
            // 获取加权后所得的和
            sum += (j * wi[i]);
        }
        // 匹配校验码
        String Ai = "10x987654342";
        // 获取验证码索引:
        int index = sum % 11;
        String str6 = Ai.substring(index, index + 1);// 校验码

        // 输出身份证
        System.out.println(id + str6);
    }

    // 进一步日期判断
    public static boolean isDate(int year, int month, int day) {// day=29|30|31
        // 日期口诀: 一三五七八十腊(12月),三十一天永不差;平年二月二十八;闰年二月把一加 ;四六九冬(11月)三十日
        // 闰年:四年一闰,百年不闰,四百年再闰.
        if (month == 2) {// 当月份=2时
            if (day == 29 && (year % 4 == 0 && year % 100 != 0 | year % 400 == 0))
                return true;
            // 是2月非闰年
            return false;
        }
        // 天数是31天,月份却是:4|6|9|11
        if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11))
            return false;
        // 其它正常情况
        return true;
    }
相关TAG标签
上一篇:springboot 从零开始[1] gradle+mybatis注解
下一篇:开发监控Web 服务的Shell脚本
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站