身份证号码信息查询

程序说明

  • 可以根据用户输入的身份证号码,查询到身份证号码中的一些信息(如:归属地、性别、出生日期、校验位 等信息)

方法一(自己实现 身份证信息提取类 - IdCardIdentify )

package IDCard.Identify;

import java.util.Calendar;
import java.util.regex.Pattern;


/** 
 * 类说明:身份证合法性校验 
 * --18位身份证号码 
 * :第7、8、9、10位为出生年份(四位数),第11、第12位为出生月份,第13、14位代表出生日期,第17位代表性别,奇数为男,偶数为女。 
 */ 

/**
 *  类说明:
 *  getInfo(String id) :获取身份证号信息
 *  isValidate18Idcard(String idcard) :验证身份证号码是否有效
 * @author Micheal
 */

public class IdCardIdentify {
	
	/**
	 * 根据 地址码、出生日期码、顺序码、校验码
	 * 获取地址、生日、年龄、性别、校验位
	 * @param IDNumber
	 */
	public void getInfo(String id){
		String province = "", birthday = "", gender = "", Check_Digit = "";
		
		String province_str = id.substring(0, 2);//省份
		String birthday_str = id.substring(6, 14);//生日
		String gender_str = id.substring(16, 17);//性别位
		String Check_Digit_str = id.substring(17, 18);//校验位
		
		for(int i=0;i<cityCode.length;i++) {
			if(province_str.equals(cityCode[i])) {
				province = codeAndCity[i][1];
			}
		}
		birthday = birthday_str.substring(0, 4)+"年"+birthday_str.substring(4, 6)+"月"+birthday_str.substring(6, 8)+"日";
		gender = (Integer.parseInt(gender_str)%2==0)?"女":"男";
		Check_Digit = Check_Digit_str;
		Calendar cale = Calendar.getInstance();  
        int year = cale.get(Calendar.YEAR);
		int age = year - Integer.parseInt(birthday_str.substring(0, 4));
		System.out.println("身份证号码为 "+id+" 的信息是");
        System.out.println("省份为: "+province);
		System.out.println("生日为: "+birthday);
		System.out.println("年龄为: "+age);
		System.out.println("性别为: "+gender);
		System.out.println("校验位为: "+Check_Digit);
	}
	
	/** 
     * 省,直辖市代码表: { 11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古", 
     * 21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏", 
     * 33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南", 
     * 42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆", 
     * 51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃", 
     * 63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"} 
     */
	protected String codeAndCity[][] = { { "11", "北京" }, { "12", "天津" },
			{ "13", "河北" }, { "14", "山西" }, { "15", "内蒙古" }, { "21", "辽宁" }, 
			{ "22", "吉林" }, { "23", "黑龙江" }, { "31", "上海" }, { "32", "江苏" }, 
			{ "33", "浙江" }, { "34", "安徽" }, { "35", "福建" }, { "36", "江西" }, 
			{ "37", "山东" }, { "41", "河南" }, { "42", "湖北" }, { "43", "湖南" }, 
			{ "44", "广东" }, { "45", "广西" }, { "46", "海南" }, { "50", "重庆" }, 
			{ "51", "四川" }, { "52", "贵州" }, { "53", "云南" }, { "54", "西藏" }, 
			{ "61", "陕西" }, { "62", "甘肃" }, { "63", "青海" }, { "64", "宁夏" }, 
			{ "65", "新疆" }, { "71", "台湾" }, { "81", "香港" }, { "82", "澳门" }, 
			{ "91", "国外" } };
	
	private String cityCode[] = { "11", "12", "13", "14", "15", "21", "22", 
			"23", "31", "32", "33", "34", "35", "36", "37", "41", "42", "43", 
			"44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", 
			"64", "65", "71", "81", "82", "91" }; 

	// 每位加权因子  17 位权值
	private int power[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; 
	
	// 第18位校检码  
	private String verifyCode[] = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
	
	
	
	/** 
     * 判断18位身份证的合法性 
     * 根据〖中华人民共和国国家标准GB11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。 
     * 排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 
     * 顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同 日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配 给女性。 
	 *
     * 1.前1、2位数字表示:所在省份的代码; 2.第3、4位数字表示:所在城市的代码; 3.第5、6位数字表示:所在区县的代码; 
     * 4.第7~14位数字表示:出生年、月、日; 5.第15、16位数字表示:所在地的派出所的代码; 
     * 6.第17位数字表示性别:奇数表示男性,偶数表示女性; 
     * 7.第18位数字是校检码:也有的说是个人信息码,一般是随计算机的随机产生,用来检验身份证的正确性。校检码可以是0~9的数字,有时也用x表示。 
     * 
     * 第十八位数字(校验码)的计算方法为: 
	 * 1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 
     * 2.将这17位数字和系数相乘的结果相加。 
     * 3.用加出来和除以11,看余数是多少? 
     * 4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。 
     * 5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。 
	 *
     */ 
	public boolean isValidate18Idcard(String idcard) { 
		// 获取前17位  
		String idcard17 = idcard.substring(0, 17); 
		// 获取第18位  
		String idcard18Code = idcard.substring(17, 18); 
		char c[] = null; 
		String checkCode = ""; 
		
		// 第一步:非18位为假  
		if (idcard.length() != 18) { 
			System.out.println("身份证位数不对,理论18位,实际"+idcard.length()+" 位!!!");
			return false; 
		} else {
			// 第二步:检测是否为17位数字加一位校验位数字 、校验码可以为‘X’
			if (!is18Idcard(idcard)) { 
				System.out.println("身份证类型不符合!!!");
				return false; 
			} else { 
				// 第三步:省份是否有效
				boolean flag = false;
				for(int i=0;i<cityCode.length;i++) {
					if(idcard.substring(0, 2).equals(cityCode[i])) {
						flag = true;
						break;
					}
				}
				if(!flag) {
					System.out.println("输入的是无效省份!!!");
					return false;
				}else {
					// 第四步:日期是否合法
					String date_str = idcard.substring(6, 14);
					int year_temp = Integer.parseInt(date_str.substring(0, 4));
					int month_temp = Integer.parseInt(date_str.substring(4, 6));
					int day_temp = Integer.parseInt(date_str.substring(6, 8));
					if(!valiDate(year_temp, month_temp, day_temp)) {
						System.out.println("出生日期不合法!!!");
						return false;
					}else {
						// 第五步:校验位 检验(见下面的程序)
						c = idcard17.toCharArray();
					}
				}
			}
		}
		
		// 校验位 检验
		if (null != c) { 
			int bit[] = new int[idcard17.length()]; 
			bit = converCharToInt(c); 
			int sum17 = 0; 
			// 获取17位数字码与权值相乘相加的结果
			sum17 = getPowerSum(bit); 
			// 将和值与11取模得到余数进行校验码判断  
			checkCode = getCheckCodeBySum(sum17); 
			if (null == checkCode) { 
				return false; 
			} 
			// 将身份证的第18位与算出来的校码进行匹配,不相等就为假
			if (!idcard18Code.equalsIgnoreCase(checkCode)) { 
				System.out.println("计算出来的校验位为 :"+ checkCode +"; 实际的校验位为:"+idcard18Code);
				return false; 
			} 
		} 
		return true; 
	} 
	
	/** 
     * 将和值与11取模得到余数进行校验码判断
     * @param sum17 
     * @return 校验位 
     */ 
	public String getCheckCodeBySum(int sum17) { 
		String checkCode = null; 
		switch (sum17 % 11) {
		case 10: 
			checkCode = "2"; 
			break;
		case 9: 
			checkCode = "3"; 
			break;
		case 8: 
			checkCode = "4"; 
			break; 
		case 7:
			checkCode = "5"; 
			break;
		case 6: 
			checkCode = "6"; 
			break;
		case 5: 
			checkCode = "7"; 
			break;
		case 4: 
			checkCode = "8"; 
			break;
		case 3:	
			checkCode = "9";
			break;
		case 2:
			checkCode = "x"; 
			break; 
		case 1: 
			checkCode = "0"; 
			break;
		case 0:
			checkCode = "1"; 
			break; 
		}
		 return checkCode;
	} 
	
	/** 
     * 将身份证的每位和对应位的加权因子相乘之后,再得到和值 
     */ 
	public int getPowerSum(int[] bit) {
		int sum = 0; 
		if (power.length != bit.length) {
			return sum; 
		}

		for (int i = 0; i < bit.length; i++) {
			for (int j = 0; j < power.length; j++) {
				if (i == j) {
					sum = sum + bit[i] * power[j]; 
				} 
			}	
		}
		return sum; 
	} 
	
	
	/** 
     * 将字符数组转为整型数组 
     */
	public int[] converCharToInt(char[] c) throws NumberFormatException {
		int[] a = new int[c.length]; 
		int k = 0; 
		for (char temp : c) { 
			a[k++] = Integer.parseInt(String.valueOf(temp)); 
		}
		return a; 
	} 

	/** 
     * 18位身份证号码的基本数字和位数验校 
     * @param idcard 
     * @return 
     */ 
	public boolean is18Idcard(String idcard) { 
		return Pattern.matches("^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|x|X]{1})$", idcard);
	} 
	
	//如果字符为空,则返回false,否则判断是否为数字,用正则表达式判断。
	public boolean isDigital(String str) { 
		return str == null || "".equals(str) ? false : str.matches("^[0-9]*$"); 
	}
	
	//如果字符为空,则返回false,否则判断是否为数字,用正则表达式判断。
	public boolean isIdValid(String id) { 
		return id == null || "".equals(id) ? false : id.matches("\\d{17}(?:\\d|x|X)$"); 
	} 
	
		
	/** 
	 * 验证小于当前日期 是否有效 
	 * @param iYear  待验证日期(年) 
	 * @param iMonth 待验证日期(月 1-12) 
	 * @param iDate  待验证日期(日) 
	 * @return 是否有效 
	 */  
	 public boolean valiDate(int iYear, int iMonth, int iDate) {  
	     Calendar cal = Calendar.getInstance();  
	     int year = cal.get(Calendar.YEAR);  
	     int datePerMonth;  
	     int MIN = 1850; //假定最小年份
	     if (iYear < MIN || iYear >= year) {  
	         return false;  
	     }  
	     if (iMonth < 1 || iMonth > 12) {  
	         return false;  
	     }  
	     switch (iMonth) {  
	     case 4:  
	     case 6:  
	     case 9:  
	     case 11:  
	         datePerMonth = 30;  
	         break;  
	     case 2:  
	         boolean dm = ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 400 == 0)) && (iYear > MIN && iYear < year);  
	         datePerMonth = dm ? 29 : 28;  
	         break;  
	     default:  
	         datePerMonth = 31;  
	     }  
	     return (iDate >= 1) && (iDate <= datePerMonth);  
	 }  
}

  • 测试类:
package IDCard.Identify;

public class MyTest {
	public static void main(String[] args) {
		IdCardIdentify idCardIdentify = new IdCardIdentify();
		// 随机 身份证数字 生成网站: http://sfz.uzuzuz.com/
		// http://jbjb.zouri.jp
		String id = "110101199003077299"; 
		if(idCardIdentify.isValidate18Idcard(id)) {
			System.out.println("有效的身份证号码");
			idCardIdentify.getInfo(id);
		}else {
			System.out.println("无效的身份证号码");
		}
		
	}
}

  • 运行结果:
    身份证号码信息查询_第1张图片

方法二(调用第三方接口)

  • 参考博客:身份证归属地查询免费api接口代码
  • 和我上述自己写的 身份证信息提取类 比较:
    优点:该API可以更加精确的查询到身份证的归属地
    缺点:需要联网
  • 话不多说,直接上代码(两个类)

IdCard 类 — 身份证实体类

package IDCard.Identify2;

/**
 * 身份证实体类
 * @author Micheal
 * @version 1.0
 *  身份证归属地查询免费api接口代码
 *  根据身份证编号 查询归属地信息
 *  
 *  身份证实体类
 */
public class IdCard {
	// 身份证号码
	private String idCard;
	// 出生日期
	private String born;
	// 性别
	private String sex;
	// 所在地区
	private String att;
	public String getIdCard() {
		return idCard;
	}
	public void setIdCard(String idCard) {
		this.idCard = idCard;
	}
	public String getBorn() {
		return born;
	}
	public void setBorn(String born) {
		this.born = born;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getAtt() {
		return att;
	}
	public void setAtt(String att) {
		this.att = att;
	}
}

IdCardService类+ 测试函数

package IDCard.Identify2;

import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.UnknownHostException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import IDCard.Identify2.IdCard;
 
/**
 * 身份证信息服务接口类
 * @author Micheal
 * @version 1.0
 */
public class IdCardService {
	
	/**
	 * 生成身份证信息
	 * @param cardNo
	 * @return 返回身份证信息
	 * @throws UnsupportedEncodingException
	 */
	public static String getIdCardDetail(String cardNo) throws UnsupportedEncodingException{
		// 获取身份证信息
		IdCard idcard = getIdCardInfo(cardNo);
		
		// 存储文本信息
		StringBuffer news = new StringBuffer();
		
		if (idcard != null) {
			news.append("所属地区:"+idcard.getAtt()).append("\n");
			news.append("出生日期:"+idcard.getBorn()).append("\n");
			news.append("性别:"+idcard.getSex()).append("\n");
		}
		
		if(news.length() == 0){
			news.append("身份证号码").append(cardNo).append("不存在,请重新输入!");
		}
		
		return news.toString();
	}
	
	/**
	 * 获取身份证信息
	 * @param cardNo
	 * @return 返回身份证信息
	 */
	public static IdCard getIdCardInfo(String cardNo){
		URL url = null;
		IdCard idCard = new IdCard();
		try{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
			DocumentBuilder builder = factory.newDocumentBuilder();
			
			url = new URL("http://api.k780.com:88/?app=idcard.get&idcard="+cardNo+"&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=xml");
			
			System.out.println(url);
			
			Document doc = builder.parse(url.openStream());
			NodeList node = doc.getElementsByTagName("result"); 
			
			for(int i=0;i<node.getLength();i++){ 
				String idcard = "";
				String born = "";
				String sex = "";
				String att = "";
				if(doc.getElementsByTagName("idcard").item(i).getFirstChild() != null){
					idcard = doc.getElementsByTagName("idcard").item(i).getFirstChild().getNodeValue();
				}
				if(doc.getElementsByTagName("born").item(i).getFirstChild() != null){
					born = doc.getElementsByTagName("born").item(i).getFirstChild().getNodeValue();
				}
				if(doc.getElementsByTagName("sex").item(i).getFirstChild() != null){
					sex = doc.getElementsByTagName("sex").item(i).getFirstChild().getNodeValue();
				}
				if(doc.getElementsByTagName("att").item(i).getFirstChild() != null){
					att = doc.getElementsByTagName("att").item(i).getFirstChild().getNodeValue();
				}
				idCard.setIdCard(idcard);
				idCard.setBorn(born);
				idCard.setSex(sex);
				idCard.setAtt(att);
			}
			
		}catch(UnknownHostException uhe) {
			System.out.println("无法连接网络");
			System.out.println(uhe.getMessage());
			uhe.printStackTrace();
		}catch(Exception e){
			e.printStackTrace();
		}
		return idCard;
	}
	
	public static void main(String[] args){
		try {
			System.out.print(getIdCardDetail("110101199003070054"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}


  • 运行截图
    身份证号码信息查询_第2张图片

你可能感兴趣的:(编程)