验证身份证号是否合法的小程序(正则表达式)

        先把代码粘在这,大家没事可以帮我测试一下,看看哪有不对的地方!(这个程序只是大概的估算一下身份证号的合法区间,也就是说所有合法的身份证号都能通过验证,有些紧邻合法边界的“假身份证号”应该也可以,本程序只能对身份证号进行匹配验证,对唯一性不能验证)

import java.util.Scanner;

public class IdTest {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        String ID;

        do{
            System.out.println("请输入您的身份证");
            ID = input.next();

            String regex = "(1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|71|81|82|90)([0-5][0-9]|90)(\\d{2})(19|20)(\\d{2})((0[13578][1-9]|0[13578][12][0-9]|0[13578]3[01]|1[02]3[01])|(0[469][1-9]|0[469][12][0-9]|30)|(02[1-9]|02[12][0-9]))(\\d{3})([0-9]|x)";

            if(ID.matches(regex)){
            System.out.println("身份证号正确");
           }else{
            System.out.println("身份证号非法");
           }

        }while(!"quit".equals(ID));

    input.close();
    }
}

GitHub:https://gist.github.com/TianYu-hpu/9975526#file-idtest

    这个是我花了大概一个小时的时间写出来的,主要是得弄清楚身份证号上每位数字代表的含义.由于这个数据采集量少,仅把所有的省份号都做了验证,如果不是这些省份的"身份号",那么将通不过这个验证。但并没有达到地级市和县级市这种精确度,想要在尽量少的代码情况下验证所有,这个也是不太现实的。因此这个验证并不是完美无缺的。

现简要介绍一下身份证号每位数字的意义:

    1~6位为地区代码,其中1、2位数为各省级政府的代码,3、4位数为地、市级政府的代码,5、6位数为县、区级政府代码。如13(河北省)04(邯郸市)29(永年县) 
7~14位为出生年月日 
15~17位为顺序号,是县、区级政府所辖派出所的分配码,每个派出所分配码为10个连续号码,例如“000-009”或“060-069”,其中单数为男性分配码,双数为女性分配码,如遇同年同月同日有两人以上时顺延第二、第三、第四、第五个分配码。如:007的就是个男生 而且和他同年月日生的男生至少有两个 他们的后四位是001* 和 003* 

       18位为效验位(识别码),通过复杂公式算出,普遍采用计算机自动生成。是前面17位的一种检验代码,如果你改变了前面某个数字而后面的效验代码不响应改变就会被计算软件判断为非法身份正号码。X也是效验代码的一中

重点在这:

        从网上下了一份《中华人民共和国行政区划代码》上面表明了每个省市县的行政编码。由于数据采集量巨大,以至于不能再短时间内完成,因此将地级市和县级市只是做了笼统的匹配(中国的地级市和县级市大概在一个区间段内,也就是身份证号的3-6位,3,4位是标明地级市的编码,大概排列区间在00-53,不过还有一个偏远地区的编号为一个孤零零的90,也就是说没有拿个地级市的编号是在54-89之间的,这里也做了统计,作为县级市,统计的数据量就更大了,因此只是做了粗略的统计,因为县级市的编号在地级市的下面,可能一个地级市下面的县级市编号是从00-10,但是有的地级市下面的县级市编号又是从80-90这样的等等,因此无法做到每个地级市下面只能匹配相应编号的县级市。这里也只是做了大概的统计所有县级市的编码实在00-99之间的,因此在正则匹配的时候用了\\d{2}来对应县级市的编号)。这样能保证只要是合法的就能匹配,但是在合法边缘的这些身份证号也可能会匹配(比如说北京市的县级市编号可能是在00-10之间,但是如果输入的编号的11-99之间也是可以的,之所以没有做那么精确一方面是这方面的数据才较量巨大,一方面是如果实现的话代码行数太多不容易理解)。

下面分析上面用红色字体标记的这么一长串的正则表达式

(1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|71|81|82|90)

这段是为了匹配省份和直辖市的行政区划代码-身份证号的1,2位(这个是对中国所有的省份和直辖市的行政区都做了统计,这么做的主要原因就是数据采集量非常小,才三十多个,和后面的市和县的统计相比这个任务是小的多的)

([0-5][0-9]|90)

身份证号的3,4位,粗略的统计了一下市的行政代码在那个区间分布(大致是在00-53之间分布,不过偏远地区有一个是90的,也在里面包含,因此在统计的时候也要把这个匹配上)

(\\d{2})

身份证号的5,6位,用来匹配县级的行政编码。没什么可说的。

(19|20)(\\d{2})((0[13578][1-9]|0[13578][12][0-9]|0[13578]3[01]|1[02]3[01])|(0[469][1-9]|0[469][12][0-9]|30)|(02[1-9]|02[12][0-9]))

这段是为了检验出生日期是否合法,不合法的值都不会匹配,比如说2月不可能有30和31号等等。

(\\d{3})([0-9]|x)

        这段是为了匹配身份证号的后4位,根据国家1999年的第二代身份证号的标准,后面是用来判断这个是男性还是女性,并且根据身份证最后一位的校验码来判断前面的值是否能够以某种方式退出来最后一位的校验码,由于计算过于复杂,这里再次忽略。

        这段代码的优点就是比现在网上的一些身份证号正则表达式匹配更准确一些(据我做这个匹配之前的观察),然后这个代码的缺点虽然能将合法的身份证号匹配成功,但是一些紧邻合法的非法字符也非常有可能匹配成功。并不是说程序做不到这么精确,只是如果那样做的话,代价会很高。我曾是想过如果对所有非法的身份证号都能匹配失败的话,那么在不适用数据库这种庞然大物的情况下,如果想要是代码在50行以内,这个将非常有可能是最佳做法。

       之前了解到12306网站在买票的时候输入的身份证号的时候应该没有加身份证是否合法的验证功能,导致很多黄牛可以用一些不合法的身份证好来买车票(比如说身份证号全0或全1的这样的身份证号也是可以在12306网站上买到票的)。我在想可能12306网站设计人员也想到过要验证身份证号的唯一性和合法性。可是这样带来的问题是数据访问量极大。每个登陆的人都要验证身份证号是否合法的话,那么对于服务器来说,就要不断的访问数据库,加重服务器的负担。倘若使用这段正则表达式进行验证的话就会将这写黄牛份子直接排除在外。这个只是自己理论上想到的应用方法。不知道可以尝试不可以。理论上是可行的。如果加上这段验证,那么这段验证的功能在服务器内存上只用存在一份就可以了。不想利用数据库来查看该身份证是否合法。增加服务器访问数据库的次数。加上这段正则验证原则上可以极大的减轻服务器的压力。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值