一、首先弄清楚一些东西:
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 ? '男' : '女');
}
}
四、结果
五、源代码下载地址:下载地址