查询身份证信息的JAVA实现

简介:   在这里,我所使用的是网易有道的接口,把网址http://www.youdao.com/smartresult-xml/search.s?type=id&q= + 要查询的身份证号,粘贴到浏览器上打开,可以看到返回的是一个表示结果的XML文件。

  在这里,我所使用的是网易有道的接口,把网址http://www.youdao.com/smartresult-xml/search.s?type=id&q= + 要查询的身份证号,粘贴到浏览器上打开,可以看到返回的是一个表示结果的XML文件。目前未发现使用限制。

  首先在浏览器 上测试一个有效的身份证号,查看源文件,可以看到返回的信息中,有四个元素是我们需要的,即code身份证号码,location身份证发证地,birthday生日,gender性别。再试一下查询无效的身份证号,只有一个<smartresult/>。

  创建一个类,表示身份证信息,内容如下(get及set方法省略),为方便测试,还得覆写toString方法,将所有内容打印出来:


public class IdCard {

	private String id;
	private String location;
	private String birthday;
	private String gender;
}

  然后从网上下载查询返回的结果,并判断该身份证号是否有效。在前面的,已经知道如果查询不到身份证信息,将返回<smartresult />,否则,返回的是<smartresult> 身份证详细内容</smartresult>。实现的代码如下:


	/**
	 * 根据身份证号查询相关信息。
	 * 
	 * @param id
	 *            身份证号
	 */
	public IdCard query(String id) {
		String info = null;
		try {
			info = getStringFromUrl(
					"http://www.youdao.com/smartresult-xml/search.s?type=id&q="
							+ id, "gbk");
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
		if ( info == null || info.contains("<smartresult/>")) {
			return null;  
		}
//		System.out.println(info);
		IdCard idCard = parseXML(info);
//		System.out.println(idCard);
		return idCard;
	}

  该方法接收一个表示身份证号的字符串,与查询地址拼接,然后获取该地址的数据,如果返回的是null指针,表示无法下载到数据,如果返回的数据库包含了<smartresult/>标签,则说明查询不到结果。在上面的代码中,由于自己只需要查询到身份证号码的结果的情况并进行进一步的操作,所对将另两种作一起判断,返回空指针。这个亦可在if语句中分别判断并给出不同的提示。getStringFromUrl是自己写的一个方法,共有两个参数,第一个表示请求的网址,第二个表示编码格式。该方法实现也比较简单,内容如下:


	/**
	 * 根据URL名得到输入流。
	 * 
	 * @param urlStr
	 *            URL名。
	 * 
	 * @return 得到的输入流。
	 * 
	 * @throws MalformedURLException
	 *             如果字符串指定未知协议。
	 * @throws IOException
	 *             如果发生 I/O 错误。
	 */
	private String getStringFromUrl(String urlStr, String charsetName) throws MalformedURLException, IOException {
		URL url = new URL(urlStr);
		HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
		InputStream in = urlConn.getInputStream();
		String string = InputStreamToString(in, charsetName);
		return string;
	}

在上面的方法中,得到的是InputStream类型的对象,还需要转换成String类型。这个可以在网上找,代码如下:


	/**
	 * 将InputStream转换成String
	 * @param urlStr
	 * @param charsetName  字符集名
	 * @return
	 */
	private String InputStreamToString ( InputStream in, String charsetName) {
		
		if (in == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		String temp = null;
		try {
			BufferedReader bf = new BufferedReader(new InputStreamReader(in, charsetName));
			while ((temp = bf.readLine()) != null) {
				sb.append(temp).append("\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} 
		return sb.toString();
	}

  到这里,我们已经能得到一个String类型的结果了。下面将对这个结果进行解析。由于内容较简单,也可对结果用正则表示式提取数据。我这里用到的是XMLReader类,来解析XML文件。用这种方法,需要实现ContentHandler接口。下面的代码中,是通过继承DefaultHandler类并重写里面的方法来实现的。


public class MyContentHandler extends DefaultHandler {

	private IdCard idCard;
	private String tagName;
	
	public MyContentHandler(IdCard idCard) {
		this.idCard = idCard;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String tmp = new String(ch, start, length);
		if (tagName.equals("code")) {
			idCard.setId(tmp);
		} else if (tagName.equals("location")) {
			idCard.setLocation(tmp);
		} else if (tagName.equals("birthday")) {
			idCard.setBirthYear(tmp.substring(0, 4));
			idCard.setBirthMonth(tmp.substring(4, 6));
			idCard.setBirthDay(tmp.substring(6, 8));
		} else if (tagName.equals("gender")) {
			idCard.setGender(tmp);
		}
	}

	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		tagName = "";
	}

	@Override
	public void startDocument() throws SAXException {
		super.startDocument();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		this.tagName = localName;
		if ("".equals(localName)) {
			this.tagName = qName;
		}
//		System.out.println("uri:" + uri + ", localName:" + localName + ", qName:" + qName);
	}

	public IdCard getIdCard() {
		return idCard;
	}
}

  上面的代码可能还不完善。其中的成员变量tagName,是为了对读到的元素进行标记。关于这段代码,可以参数mars-droid第一季视频中XML文件那一集。在这里其中在startElement方法中,我对tagName的赋值是这样的:


		this.tagName = localName;
		if ("".equals(localName)) {
			this.tagName = qName;
		}

  看起来貌似很麻烦。这个也是我一时想到的。我在使用的时候悲剧地发现,第一次使用时读到的如code等元素,是赋值在qName中的,但是移植到Android中时,貌似却是读到localName的,又不知它会不会变成赋值到qName中去,只好用这个方法了。

  实现了ContentHandler之后,下面对其使用的代码如下:


	/**
	 * 得析得到的XML字符串的信息
	 * @param info
	 * @return
	 */
	private IdCard parseXML(String info) {
		IdCard idCard = new IdCard();
		
		try {
			XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
			MyContentHandler contentHandler = new MyContentHandler(idCard);
			xmlReader.setContentHandler(contentHandler);
			xmlReader.parse(new InputSource(new StringReader(info)));
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return idCard;
	}

 这样就得到了IdCard对象了。

  以上内容中,如果有问题,或有更好的实现方法,还望大家指教。我是菜鸟。


目录
打赏
0
0
0
0
4
分享
相关文章
|
2月前
|
Java使用sql查询mongodb
通过MongoDB Atlas Data Lake或Apache Drill,可以在Java中使用SQL语法查询MongoDB数据。这两种方法都需要适当的配置和依赖库的支持。希望本文提供的示例和说明能够帮助开发者实现这一目标。
57 17
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
132 6
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
106 7
|
3月前
|
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
127 9
|
4月前
|
使用java在未知表字段情况下通过sql查询信息
使用java在未知表字段情况下通过sql查询信息
57 8
Java智慧工地信息管理平台源码 智慧工地信息化解决方案SaaS源码 支持二次开发
智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
74 3
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
117 2
面试官:java8中parallelStream提升数倍查询效率是怎样实现的
业务场景 在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数,订单总金额,支出总金额等。。。这些业务通常都不是存在同一张表中,我们需要依次查询出来然后封装成所需要的对象返回给前端。那么在此过程中,就可以把这个接口中“大任务”拆分成N个小任务,异步执行这些小任务,等到最后一个小任务执行完,把所有任务的执行结果封装到返回结果中,统一返回到前端展示。
面试官:java8中parallelStream提升数倍查询效率是怎样实现的
|
7天前
|
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
117 60
【Java并发】【线程池】带你从0-1入门线程池
|
3天前
|
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
40 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等