Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 474|回复: 0

[Java基础知识]身份证识别(java)

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-9-30 17:47:05 | 显示全部楼层 |阅读模式
    身份号码是特征组合码,由十七位数字本体码和一位校验码组成。

        排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

       身份证地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。

       身份证出生日期码表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。

       身份证顺序码表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

    身份证校验码是十七位数字本体码加权求和而得出的。  
      
       
       
         
       

         
       
      
    编码规则:
        公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码,可以用字母表示如为ABCDEFYYYYMMDDXXXR。其含义如下:
    1. 地址码(ABCDEF):表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。 2. 出生日期码(YYYYMMDD):表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日分别用4位、2位(不足两位加0)、2位(不足两位加0)数字表示,之间不用分隔符。 3. 顺序码(XXX):表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。 4.校验码(R),一位数字,通过前17位数字根据一定计算得出,检验码分别是“0、1、2、……10”共11个数字,当检验码为“10”时,为了保证公民身份证号码18位,所以用“X”表示。 1、关于中国居民身份证的常识:
    我国现行使用公民身份证号码有两种尊循两个国家标准,〖GB 11643-1989〗和〖GB 11643-1999〗。
    〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。

            〖GB 11643-1999〗中规定的是18位身份证号码:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
    地址码:表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
    出生日期码:表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。
    顺序码:表示同一地址码所标识的区域范围内,对同年、同月、同日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。
    校验码:是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。  关于身份证号码最后一位的校验码的算法如下:
    ∑(a*W) mod 11 ( i = 2, 3, ..., 18 )
    "*" : 表示乘号
    i: 表示身份证号码每一位的序号,从右至左,最左侧为18,最右侧为1。
    a: 表示身份证号码第 i 位上的号码
    W: 表示第 i 位上的权值 W = 2^(i-1) mod 11
    设:R = ∑(a*W) mod 11 ( i = 2, 3, ..., 18 )
    C = 身份证号码的校验码  则R和C之间的对应关系如下表:
    R:0 1 2 3 4 5 6 7 8 9 10
    C:1 0 X 9 8 7 6 5 4 3 2  由此看出 X 就是 10,罗马数字中的 10 就是X,所以在新标准的身份证号码中可能含有非数字的字母X。 算法:
    1. import java.text.DateFormat;
    2. import java.text.NumberFormat;
    3. import java.text.ParseException;
    4. import java.util.Date;
    5. import java.util.Random;
    6. /**
    7. * @author 成晓旭
    8. *
    9. */
    10. public class Identity {
    11.     //位权值数组
    12.     private static byte[] Wi=new byte[17];
    13.     // 身份证前部分字符数
    14.     private static final byte fPart = 6;
    15.     // 身份证算法求模关键值
    16.     private static final byte fMod = 11;
    17.     //旧身份证长度
    18.     private static final byte oldIDLen = 15;
    19.     //新身份证长度
    20.     private static final byte newIDLen = 18;
    21.     //新身份证年份标志
    22.     private static final String yearFlag = "19";
    23.      //校验码串
    24.     private static final String CheckCode="10X98765432";
    25.      //最小的行政区划码
    26.     private static final int minCode = 150000;
    27.      // 最大的行政区划码
    28.     private static final int maxCode = 700000;
    29.      //旧身份证号码
    30.      //private String oldIDCard="";
    31.      //新身份证号码
    32.      //private String newIDCard="";
    33.      //地区及编码
    34.       //private String Area[][2] =
    35.     private static void setWiBuffer(){
    36.         for(int i=0;i< Wi.length;i++){   
    37.             int k = (int) Math.pow(2, (Wi.length-i));
    38.             Wi[i] = (byte)(k % fMod);
    39.         }
    40.     }
    41.     //获取新身份证的最后一位:检验位
    42.     private static String getCheckFlag(String idCard){
    43.         int sum = 0;
    44.        //进行加权求和
    45.         for(int i=0; i< 17; i++){        
    46.             sum += Integer.parseInt(idCard.substring(i,i+1)) * Wi[i];
    47.         }
    48.         //取模运算,得到模值
    49.         byte iCode = (byte) (sum % fMod);
    50.         return CheckCode.substring(iCode,iCode+1);
    51.     }
    52.     //判断串长度的合法性
    53.     private static boolean checkLength(final String idCard,boolean newIDFlag){
    54.         boolean right = (idCard.length() == oldIDLen) || (idCard.length() == newIDLen);
    55.         newIDFlag = false;
    56.         if(right){
    57.             newIDFlag = (idCard.length() == newIDLen);
    58.         }
    59.         return right;
    60.     }
    61.     //获取时间串
    62.     private static String getIDDate(final String idCard,boolean newIDFlag){
    63.         String dateStr = "";
    64.         if(newIDFlag)
    65.             dateStr = idCard.substring(fPart,fPart+8);
    66.         else
    67.             dateStr = yearFlag + idCard.substring(fPart,fPart+6);
    68.         return dateStr;
    69.     }
    70.     //判断时间合法性
    71.     private static boolean checkDate(final String dateSource){
    72.         String dateStr = dateSource.substring(0,4)+"-"+dateSource.substring(4,6)+"-"+dateSource.substring(6,8);
    73.         System.out.println(dateStr);
    74.         DateFormat df = DateFormat.getDateInstance();
    75.         df.setLenient(false);
    76.         try {
    77.             Date date= df.parse(dateStr);
    78.             return (date!=null);
    79.         } catch (ParseException e) {
    80.             // TODO Auto-generated catch block
    81.             return false;
    82.         }
    83.     }
    84.     //旧身份证转换成新身份证号码
    85.     public static String getNewIDCard(final String oldIDCard){
    86.         //初始化方法
    87.         Identity.setWiBuffer();
    88.         if(!checkIDCard(oldIDCard)){
    89.             return oldIDCard;
    90.         }
    91.         String newIDCard = oldIDCard.substring(0, fPart);
    92.         newIDCard += yearFlag;
    93.         newIDCard += oldIDCard.substring(fPart, oldIDCard.length());
    94.         String ch = getCheckFlag(newIDCard);
    95.         newIDCard += ch;
    96.         return newIDCard;
    97.     }
    98.     //新身份证转换成旧身份证号码
    99.     public static String getOldIDCard(final String newIDCard){
    100.         //初始化方法
    101.         Identity.setWiBuffer();
    102.         if(!checkIDCard(newIDCard)){
    103.             return newIDCard;
    104.         }
    105.         String oldIDCard = newIDCard.substring(0,fPart)+
    106.                     newIDCard.substring(fPart+yearFlag.length(),newIDCard.length()-1);
    107.         return oldIDCard;
    108.     }
    109.     //判断身份证号码的合法性
    110.     public static boolean checkIDCard(final String idCard){
    111.         //初始化方法
    112.         Identity.setWiBuffer();
    113.         boolean isNew = false;
    114.         //String message = "";
    115.         if (!checkLength(idCard,isNew)){
    116.             //message = "ID长度异常";
    117.             return false;
    118.         }
    119.         String idDate = getIDDate(idCard, isNew);
    120.         if(!checkDate(idDate)){
    121.             //message = "ID时间异常";
    122.             return false;
    123.         }
    124.         if(isNew){
    125.             String checkFlag = getCheckFlag(idCard);
    126.             String theFlag = idCard.substring(idCard.length()-1,idCard.length());
    127.             if(!checkFlag.equals(theFlag)){
    128.                 //message = "新身份证校验位异常";
    129.                 return false;
    130.             }
    131.         }
    132.         return true;
    133.     }
    134.     //获取一个随机的"伪"身份证号码
    135.     public static String getRandomIDCard(final boolean idNewID){
    136.         //初始化方法
    137.         Identity.setWiBuffer();
    138.         Random ran = new Random();
    139.         String idCard = getAddressCode(ran)+getRandomDate(ran,idNewID)+getIDOrder(ran);
    140.         if(idNewID){
    141.             String ch = getCheckFlag(idCard);
    142.             idCard += ch;
    143.         }
    144.         return idCard;
    145.     }
    146.     //产生随机的地区编码
    147.     private static String getAddressCode(Random ran) {
    148.         if(ran==null){
    149.             return "";
    150.         }else{
    151.             int addrCode = minCode + ran.nextInt(maxCode-minCode);
    152.             return Integer.toString(addrCode);
    153.         }
    154.     }
    155.     //产生随机的出生日期
    156.     private static String getRandomDate(Random ran, boolean idNewID) {
    157.         // TODO Auto-generated method stub
    158.         if(ran==null){
    159.             return "";
    160.         }
    161.         int year = 0;
    162.         if(idNewID){
    163.             year = 1900 + ran.nextInt(2007-1900);
    164.         }else{
    165.             year = 1 + ran.nextInt(99);
    166.         }
    167.         int month = 1+ran.nextInt(12);
    168.         int day = 0;
    169.         if(month==2){
    170.             day= 1+ran.nextInt(28);
    171.         }else if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
    172.             day= 1+ran.nextInt(31);
    173.         }else{
    174.             day= 1+ran.nextInt(30);
    175.         }
    176.         NumberFormat nf = NumberFormat.getIntegerInstance();
    177.         nf.setMaximumIntegerDigits(2);
    178.         nf.setMinimumIntegerDigits(2);
    179.         String dateStr = Integer.toString(year)+nf.format(month)+nf.format(day);
    180.         return dateStr;
    181.     }
    182.     //产生随机的序列号
    183.     private static String getIDOrder(Random ran) {
    184.         // TODO Auto-generated method stub
    185.         NumberFormat nf = NumberFormat.getIntegerInstance();
    186.         nf.setMaximumIntegerDigits(3);
    187.         nf.setMinimumIntegerDigits(3);
    188.         if(ran==null){
    189.             return "";
    190.         }else{
    191.             int order = 1+ran.nextInt(999);
    192.             return nf.format(order);
    193.         }
    194.     }
    195.     public Identity(){
    196.         setWiBuffer();
    197.     }
    198.     /**
    199.      * @param args
    200.      */
    201.     public static void main(String[] args) {
    202.         // TODO Auto-generated method stub
    203.         String randomID=Identity.getRandomIDCard(true);
    204.         System.out.println("随机身份证:"+randomID);
    205.         /*
    206.         String oldID="";
    207.         String newID=Identity.getNewIDCard(oldID);
    208.         System.out.println("旧身份证:"+oldID);
    209.         System.out.println("新身份证:"+newID);
    210.         String oldCard = Identity.getOldIDCard(newID);
    211.         System.out.println("旧身份证:"+oldCard);
    212.         /*
    213.         String dateSource="2000-9-30";
    214.         if(id.checkDate(dateSource))
    215.             System.out.println("正确时间串:"+dateSource);
    216.         else
    217.             System.out.println("错误时间串:"+dateSource);
    218.         */
    219.     }
    220. }
    复制代码



      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-9 19:27 , Processed in 0.428917 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表