Android、Java超详细的身份证验证工具
2016-07-17 18:37
429 查看
首先科普一下身份证的一些知识(知道的勿喷)
1-2 位:代表升级行政区代码
3-4 位:代表地级行政区划分代码
5-6 位:代表县区行政区分代码
7-14 位:代表出生年、月、日,例如:19900101
15-17 位:代表 顺序码,同一地区同年、同月、同日出生人的编号,奇数是男性,偶数是女性
18 位:代表校验码,如果是0-9则用0-9表示,如果是10则用X(罗马数字10)表示
注:另外有些15位的身份证号码,年份使用2位数字表示的,并且没有最后一位校验码;从1999年10月1日起,全国实行公民身份证号码制度,居民身份证编号由原15位升至18位,所以可以确定15位身份证号码的都是19xx年出生的
前17位的验证在这里就不多讲解,重点讲解一下最后一位校验码的验证,最后一位校验码等于前17位根据每一位的权重的乘积之和再除以11的余数,这里等会看代码解释
前17位每一位的的权重如下:
{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
主要代码如下
以上代码都很简单,在这讲解一下身份证验证步骤
第一步:验证身份证位数够不够
第二步:验证身份证有没有除数字以外的字符(18位身份证最后一位X除外)
第三步:验证前两位省份编码对不对
第四步:验证7-14位出生日期在不在范围内
第五步:验证最后一位校验码对不对
如以上五步都通过了验证,那么就可以说明身份证是合法的,其中任何一步验证出错,都会有相应的提示信息
1-2 位:代表升级行政区代码
3-4 位:代表地级行政区划分代码
5-6 位:代表县区行政区分代码
7-14 位:代表出生年、月、日,例如:19900101
15-17 位:代表 顺序码,同一地区同年、同月、同日出生人的编号,奇数是男性,偶数是女性
18 位:代表校验码,如果是0-9则用0-9表示,如果是10则用X(罗马数字10)表示
注:另外有些15位的身份证号码,年份使用2位数字表示的,并且没有最后一位校验码;从1999年10月1日起,全国实行公民身份证号码制度,居民身份证编号由原15位升至18位,所以可以确定15位身份证号码的都是19xx年出生的
前17位的验证在这里就不多讲解,重点讲解一下最后一位校验码的验证,最后一位校验码等于前17位根据每一位的权重的乘积之和再除以11的余数,这里等会看代码解释
前17位每一位的的权重如下:
{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
主要代码如下
/** * 验证结果类 * * @author liujingxing on 16/07/17. */ public class Result { /** * 错误消息,为空时,代表验证通过 */ private String error; public boolean isLegal() { //两个变量为默认值,即认为是合法的 return error == null || error.equals(""); } public String getError() { return error; } public void setError(String message) { this.error = message; } public void show(Context context) { if (!isLegal()) Toast.makeText(context, error, Toast.LENGTH_SHORT).show(); } }
/** * 身份证验证工具,只需要调用静态方法 validateIDNum(String) 传入身份证即可 * * @author liujingxing by 2016/07/17 * @see #validateIDNum(String) */ public class IDCardUtil { private final static int[] FACTOR = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; public static Result validateIDNum(String idNum) { Result result = new Result();// 记录验证结果 //判断身份证是否为空 if (TextUtils.isEmpty(idNum)) { result.setError("身份证号码不能为空"); return result; } //身份证号码的长度只能为15位或18位 int idNumLength = idNum.length(); if (idNumLength != 15 && idNumLength != 18) { result.setError("身份证号码应该为15位或18位"); return result; } //对身份证的字符做判断 if (!isAllNum(idNum)) { result.setError(idNum.length() == 18 ? "18位号码除最后一位外,都应为数字" : "15位号码都应为数字"); return result; } if (idNum.contains("x")) { result.setError("身份证x必须为大写"); return result; } //判断地区编码 Hashtable<String, String> h = getAreaCode(); if (h.get(idNum.substring(0, 2)) == null) { result.setError("身份证地区编码错误"); return result; } // 出生年月是否有效 String idNum17; if (idNum.length() == 18) { idNum17 = idNum.substring(0, 17); } else { //如果是15为身份证则加上出生年代:19 idNum17 = idNum.substring(0, 6) + "19" + idNum.substring(6, 15); } String strYear = idNum17.substring(6, 10);// 年份 String strMonth = idNum17.substring(10, 12);// 月份 String strDay = idNum17.substring(12, 14);// 月份 if (!validateDate(strYear + "-" + strMonth + "-" + strDay)) { result.setError("身份证生日无效"); return result; } GregorianCalendar gc = new GregorianCalendar(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); try { if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150 || (gc.getTime().getTime() - format.parse(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) { result.setError("身份证生日不在有效范围"); return result; } } catch (NumberFormatException | java.text.ParseException e) { e.printStackTrace(); } //18位的身份证对最后一位校验码进行验证 if (idNum.length() == 18 && !isCorrectID(idNum)) { result.setError("身份证无效,不是合法的身份证号码"); return resu bbf5 lt; } return result; } /** * 功能:设置地区编码 */ private static Hashtable<String, String> getAreaCode() { Hashtable<String, String> hashTable = new Hashtable<>(); hashTable.put("11", "北京"); hashTable.put("12", "天津"); hashTable.put("13", "河北"); hashTable.put("14", "山西"); hashTable.put("15", "内蒙古"); hashTable.put("21", "辽宁"); hashTable.put("22", "吉林"); hashTable.put("23", "黑龙江"); hashTable.put("31", "上海"); hashTable.put("32", "江苏"); hashTable.put("33", "浙江"); hashTable.put("34", "安徽"); hashTable.put("35", "福建"); hashTable.put("36", "江西"); hashTable.put("37", "山东"); hashTable.put("41", "河南"); hashTable.put("42", "湖北"); hashTable.put("43", "湖南"); hashTable.put("44", "广东"); hashTable.put("45", "广西"); hashTable.put("46", "海南"); hashTable.put("50", "重庆"); hashTable.put("51", "四川"); hashTable.put("52", "贵州"); hashTable.put("53", "云南"); hashTable.put("54", "西藏"); hashTable.put("61", "陕西"); hashTable.put("62", "甘肃"); hashTable.put("63", "青海"); hashTable.put("64", "宁夏"); hashTable.put("65", "新疆"); hashTable.put("71", "台湾"); hashTable.put("81", "香港"); hashTable.put("82", "澳门"); hashTable.put("91", "国外"); return hashTable; } /** * 判断身份证字符是否合法 */ private static boolean isAllNum(String idNum) { String match = idNum.length() == 18 ? "^[0-9]{17}([0-9]|X)$" : "^[0-9]{15}$"; Pattern pattern = Pattern.compile(match); Matcher isNum = pattern.matcher(idNum); return isNum.matches(); } /** * 功能:判断字符串是否为日期格式 */ private static boolean validateDate(String strDate) { Pattern pattern = Pattern.compile( "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$"); Matcher m = pattern.matcher(strDate); return m.matches(); } /** * 判断输入的身份证是否合法 * * @param idNum 18位的身份证号 * @return 合法true,反之false */ private static boolean isCorrectID(String idNum) { boolean flag = false; if (idNum == null || idNum.trim().length() != 18) { return false; } String last = getLastNumOfID(idNum.substring(0, idNum.length() - 1)); if (last.equals(String.valueOf(idNum.charAt(idNum.length() - 1)))) { flag = true; } return flag; } /** * 根据前17位身份证号,算出第18位数字 * * @param id17 前17位身份证号 * @return 第18位身份证号对应的数字 */ private static String getLastNumOfID(String id17) { int sum = sumFactor(id17); String res; if (sum == -1) { res = "输入的身份证为空"; } else if (sum == -3) { res = "输入的身份证号码不为17位"; } else { int mod = sum % 11; int last = (12 - mod) % 11; if (last == 10) { res = "X";//X代表罗马数字10 } else { res = String.valueOf(last); } } return res; } /** * 计算前17位身份证号乘以各个数的权重的总和 * * @param id17 前17位身份证号 * @return 权重的总和 */ private static int sumFactor(String id17) { if (id17 == null || id17.trim().equals("")) { return -1; //输入的身份证为空 } int len = id17.length(); if (len != 17) { return -3; //输入的身份证号码不为17位 } int sum = 0; for (int i = 0; i < len; i++) { sum += FACTOR[i] * Integer.parseInt(String.valueOf(id17.charAt(i))); } return sum; } }
以上代码都很简单,在这讲解一下身份证验证步骤
第一步:验证身份证位数够不够
第二步:验证身份证有没有除数字以外的字符(18位身份证最后一位X除外)
第三步:验证前两位省份编码对不对
第四步:验证7-14位出生日期在不在范围内
第五步:验证最后一位校验码对不对
如以上五步都通过了验证,那么就可以说明身份证是合法的,其中任何一步验证出错,都会有相应的提示信息
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法