一、首先弄清楚一些东西:
15位的旧身份证,最后一个数是单数的为男,双数的为女。
18位的新身份证,倒数第二位是单数的为男,双数的为女。
校验的计算方式:
1. 对前17位数字本体码加权求和
公式为:S = Sum(Ai * Wi), i = 0, ... , 16
其中Ai表示第i位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
2. 以11对计算结果取模
Y = mod(S, 11)
3. 根据模的值得到对应的校验码
对应关系为:
Y值: 0 1 2 3 4 5 6 7 8 9 10
校验码: 1 0 X 9 8 7 6 5 4 3 2
二、怎么得到出生地区?
因为身份证前6位代表的是其出生地方,而且都有一一对应的关系,所以直接拿着去比对就可以。
三、代码实现
- package j8;
- import java.io.BufferedReader;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.util.Properties;
- public class IdCardParser {
- public static void main(String[] args) {
- try {
- System.out.println("请输入您要查询的身份证号码:");
- InputStreamReader reader = new InputStreamReader(System.in);
- String str = new BufferedReader(reader).readLine();
- IdCard ic = IdCardParser.parse(str);
- if(ic != null){
- System.out.println(ic);
- }else{
- System.out.println("您输入的有误");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private static final byte[] factor = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9,
- 10, 5, 8, 4, 2, 1 };
- private static final char[] ch = { '1', '0', 'X', '9', '8', '7', '6', '5',
- '4', '3', '2' };
- /**
- * 15位身份证转18位身份证.失败返回null
- *
- * @param $15
- * @return
- */
- private static String $15to18(String $15) {
- if ($15 == null) {
- return null;
- }
- if ($15.length() == 18) {
- return $15;
- }
- if ($15.length() != 15) {
- return null;
- }
- StringBuilder sb = new StringBuilder($15);
- sb.insert(6, "19");// 加入年两位
- int result = 0;
- for (int i = 0; i < sb.length(); i++) {
- result += (Integer.parseInt(sb.charAt(i) + "")) * factor[i];
- }
- return sb.append(ch[result % 11]).toString();// 加入效验码
- }
- /**
- * 验证第18位效验码
- *
- * @param idCardNumber
- * @return
- */
- private static boolean check18(String idCardNumber) {
- if (idCardNumber == null || idCardNumber.length() != 18) {
- return false;
- }
- int result = 0;
- for (int i = 0; i < idCardNumber.length() - 1; i++) {
- result += (Integer.parseInt(idCardNumber.charAt(i) + ""))
- * factor[i];
- }
- return ch[result % 11] == idCardNumber.charAt(17);
- }
- /**
- * 验证出生日期是否合法
- *
- * @param idCardNumber
- * @return
- */
- private static boolean checkBirthDay(int year, int month, int day) {
- if (year < 1900 || year > 2013) {
- return false;
- }
- if (month > 12 || month < 1) {
- return false;
- }
- if (day < 1) {
- return false;
- }
- byte[] dayOfMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
- dayOfMonth[1] = 29;
- }
- return day <= dayOfMonth[month - 1];
- }
- public static IdCard parse(String idCardNumber) {
- // 检查字符串
- if (!idCardNumber.matches("\\d{15}|\\d{18}|\\d{17}(?i)X")) {
- return null;
- }
- IdCard ic = new IdCard();
- // 15->18
- idCardNumber = $15to18(idCardNumber);
- // 检查效验码
- if (idCardNumber == null || !check18(idCardNumber)) {
- return null;
- }
- // 检查出生年月
- int year = Integer.parseInt(idCardNumber.substring(6, 10));
- int month = Integer.parseInt(idCardNumber.substring(10, 12));
- int day = Integer.parseInt(idCardNumber.substring(12, 14));
- if (!checkBirthDay(year, month, day)) {
- return null;
- }
- ic.setNumber(idCardNumber);
- // 查询身份证归属地
- ic.setAddress(info.getProperty(idCardNumber.substring(0, 6)));
- ic.setBirthday(String.format("%d-%d-%d",year, month, day));
- ic.setSex(1 == (Integer.parseInt(idCardNumber.charAt(16) + "") & 1));
- return ic;
- }
- private static final Properties info;
- static {
- info = new Properties();
- try {
- info.load(new InputStreamReader(new FileInputStream(
- "IdCard.properties"), "UTF-8"));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
身份证实体类:
- package j8;
- public class IdCard {
- private String number;
- private String address;
- private String birthday;
- private boolean sex;//true男.false女
- public IdCard(){
- }
- public IdCard(String number, String address, String birthday, boolean sex) {
- this.number = number;
- this.address = address;
- this.birthday = birthday;
- this.sex = sex;
- }
- public String getNumber() {
- return number;
- }
- public void setNumber(String number) {
- this.number = number;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- public String getBirthday() {
- return birthday;
- }
- public void setBirthday(String birthday) {
- this.birthday = birthday;
- }
- public boolean isSex() {
- return sex;
- }
- public void setSex(boolean sex) {
- this.sex = sex;
- }
- public String toString(){
- return String.format("[号码:%s,地址:%s,出生:%s,性别:%s]",number,address,birthday,sex ? '男' : '女');
- }
- }
四、结果