前端时间写项目写到了排队项目,需要用到身份证读取功能,但是市面找了很久发现读取身份证的基本没有java版本的,不是c#就是c++等,定下心来,决定自己写一个java读取身份证信息的工具类,技术没有难度,采用设备是公司购买的设备,不方便透露,各大厂家应该有自己的设备和读取驱动包。

设备安装

第一步设备安装就不解释了,自己安装设备和驱动。

java项目集成读取功能

本次采用的是通过固定端口,java项目集成jna来实现读取,第一步先添加依赖

 <dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>5.3.1</version></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna-platform</artifactId><version>5.3.1</version></dependency>

然后加载 sdtapi.dll 包,市面流通的sdtapi.dll 全是32位的,所以java项目用32位jdk来运行和启动,不知道有没有64位,我反正没找到

//    public static final String dllPath="D:\\java\\dll\\";public static final String dllPath="";public static final int port=1001;public interface CLibrary extends Library {// sdtapi.dll 32位的包,开发过程切换到32位的jdk运行,CLibrary INSTANCE = (CLibrary) Native.load(dllPath+"sdtapi", CLibrary.class);//读取身份证信息 使用到如下方法int SDT_OpenPort(int iPort);int SDT_StartFindIDCard( int iPort,byte[] a,int iIfOpen );int SDT_ReadBaseFPMsg( int iPort ,byte[] pucCHMsg ,IntByReference puiCHMsgLen ,byte[] pucPHMsg ,IntByReference puiPHMsgLen,byte[] pucFPMsg,IntByReference puiFMsgLen,int iIfOpen );int SDT_SelectIDCard( int iPort ,byte[] a,int iIfOpen);int SDT_ReadBaseMsg(int iPort ,byte[] pucCHMsg ,IntByReference puiCHMsgLen ,byte[] pucPHMsg ,IntByReference puiPHMsgLen,int iIfOpen  );int SDT_GetSAMIDToStr( int iPort,byte[] strSAMID ,int iIfOpen );}

先将如上方法定义到内部类中去,这些方法对应的就是sdtapi.dll 提供的方法,下面讲解具体用法。如果是本地测试将sdtapi.dll放到项目根目录,如果是部署,路径我是写死的。以下是身份证读取的方法和过程。

 /*** 读取身份证信息:返回为空表示读取失败* @return*/public static synchronized IdcordBean readIdCord(){//打开端口int value = CLibrary.INSTANCE.SDT_OpenPort(port);System.out.println(Integer.toHexString(value));byte[] strSAMID = new byte[65] ;int samid= CLibrary.INSTANCE.SDT_GetSAMIDToStr(port, strSAMID,1);System.out.println("读取samid:"+Integer.toHexString(samid));String s = new String(strSAMID);System.out.println(s);byte[] bytes = new byte[16];//查找身份证int select = CLibrary.INSTANCE.SDT_StartFindIDCard(port, bytes,1);System.out.println("寻卡:"+Integer.toHexString(select));String s1 = new String(bytes);System.out.println(s1);//选卡int selectCode= CLibrary.INSTANCE.SDT_SelectIDCard(port, bytes,1);System.out.println("选卡:"+Integer.toHexString(selectCode));String s2 = new String(bytes);System.out.println(s2);byte[] pucCHMsg=new byte[256 + 1] ,pucPHMsg=new byte[1024 + 1],pucFPMsg=new byte[1024 + 1];IntByReference puiCHMsgLen=new IntByReference(0) , puiPHMsgLen=new IntByReference(0),puiFMsgLen=new IntByReference(0);//第一次读卡,带指纹的
//        int readOld= CLibrary.INSTANCE.SDT_ReadBaseFPMsg(port, pucCHMsg,puiCHMsgLen,pucPHMsg,puiPHMsgLen,pucFPMsg,puiFMsgLen,1);
//        System.out.println("读卡1:"+Integer.toHexString(readOld)+":");//第二次读卡,不带指纹int read= CLibrary.INSTANCE.SDT_ReadBaseMsg(port, pucCHMsg,puiCHMsgLen,pucPHMsg,puiPHMsgLen,1);System.out.println("读卡2:"+Integer.toHexString(read)+":");if(Integer.toHexString(read).equals(90+"")){byte[] byName = new byte[30];byte[] bySex = new byte[2];byte[] byRace = new byte[4];byte[] byBirth = new byte[16];byte[] byAddress = new byte[70];byte[] byID = new byte[36];byte[] byCompany = new byte[30];byte[] byBeginDate = new byte[16];byte[] byEndDate = new byte[16];System.arraycopy(pucCHMsg, 0, byName, 0, 30);System.arraycopy(pucCHMsg, 30, bySex, 0, 2);System.arraycopy(pucCHMsg, 32, byRace, 0, 4);System.arraycopy(pucCHMsg, 36, byBirth, 0, 16);System.arraycopy(pucCHMsg, 52, byAddress, 0, 70);System.arraycopy(pucCHMsg, 122, byID, 0, 36);System.arraycopy(pucCHMsg, 158, byCompany, 0, 30);System.arraycopy(pucCHMsg, 188, byBeginDate, 0, 16);System.arraycopy(pucCHMsg, 204, byEndDate, 0, 16);//解析身份证数据IdcordBean idcordBean=new IdcordBean();try {System.out.println(Arrays.toString(byName));System.out.println(Arrays.toString(byCompany));System.out.println(Arrays.toString(byAddress));byte[] namebytes=toByte(byName);byte[] companyBytes=toByte(byCompany);byte[] addressbytes=toByte(byAddress);String name = new String(namebytes, "UNICODE");String company = new String(companyBytes, "UNICODE");String address = new String(addressbytes, "UNICODE");idcordBean.setByName(name).setByCompany(company).setByAddress(address);//打印身份证信息System.out.println(name);System.out.println(company);System.out.println(address);} catch (UnsupportedEncodingException e) {e.printStackTrace();}idcordBean.setBySex(new String(bySex).replaceAll("\\u0000","")).setByID(new String(byID).replaceAll("\\u0000","")).setByRace(new String(byRace).replaceAll("\\u0000","")).setByBirth(new String(byBirth).replaceAll("\\u0000","")).setByBeginDate(new String(byBeginDate).replaceAll("\\u0000","")).setByEndDate(new String(byEndDate).replaceAll("\\u0000",""));
//            System.out.println(new String(bySex));
//            System.out.println(new String(byRace));
//            System.out.println(new String(byBirth));
//            System.out.println(new String(byID));
//            System.out.println(new String(byBeginDate));
//            System.out.println(new String(byEndDate));return idcordBean;}return null;}//身份证汉字编码解码public static byte[] toByte(byte [] source){int length=0;for (int i = 0; i < source.length; i++) {if(source[i]==32&&source[i+1]==0){length=i;break;}}System.out.println(length);byte[] obj=new byte[length+2];obj[0]=-2;obj[1]=-1;for (int i = 0; i < length; i++) {if(i%2==0){obj[i+3]=source[i];}else{obj[i+1]=source[i];}}return obj;}

readIdCord 方法是读取身份证的方法和过程,toByte 是对汉字进行转码解析的一个方法。接下来我说以下我写的过程。

先看一下结果,其他信息涉及隐私就不显示了:

第一步先调用打开设备的方法,读取一下设备信息,寻找设备上是否有卡(身份证),返回状态马是16进制的,记得比较的时候进行转换。

  //打开端口int value = CLibrary.INSTANCE.SDT_OpenPort(port);System.out.println(Integer.toHexString(value));byte[] strSAMID = new byte[65] ;int samid= CLibrary.INSTANCE.SDT_GetSAMIDToStr(port, strSAMID,1);System.out.println("读取samid:"+Integer.toHexString(samid));String s = new String(strSAMID);System.out.println(s);byte[] bytes = new byte[16];//查找身份证int select = CLibrary.INSTANCE.SDT_StartFindIDCard(port, bytes,1);System.out.println("寻卡:"+Integer.toHexString(select));String s1 = new String(bytes);System.out.println(s1);

然后选择卡片进行卡片的数据读取(提前定义一个数组,参数用内存的方式写入

IntByReference 类型传值。

调用方法的时候传入进去,然后方法内部会向设备进行一个字节码写入)

//选卡int selectCode= CLibrary.INSTANCE.SDT_SelectIDCard(port, bytes,1);System.out.println("选卡:"+Integer.toHexString(selectCode));String s2 = new String(bytes);System.out.println(s2);byte[] pucCHMsg=new byte[256 + 1] ,pucPHMsg=new byte[1024 + 1],pucFPMsg=new byte[1024 + 1];IntByReference puiCHMsgLen=new IntByReference(0) , puiPHMsgLen=new IntByReference(0),puiFMsgLen=new IntByReference(0);//第一次读卡,带指纹的
//        int readOld= CLibrary.INSTANCE.SDT_ReadBaseFPMsg(port, pucCHMsg,puiCHMsgLen,pucPHMsg,puiPHMsgLen,pucFPMsg,puiFMsgLen,1);
//        System.out.println("读卡1:"+Integer.toHexString(readOld)+":");//第二次读卡,不带指纹int read= CLibrary.INSTANCE.SDT_ReadBaseMsg(port, pucCHMsg,puiCHMsgLen,pucPHMsg,puiPHMsgLen,1);System.out.println("读卡2:"+Integer.toHexString(read)+":");

然后对读取结果进行处理,我这个设备结果16进制的90是成功状态

if(Integer.toHexString(read).equals(90+"")){byte[] byName = new byte[30];byte[] bySex = new byte[2];byte[] byRace = new byte[4];byte[] byBirth = new byte[16];byte[] byAddress = new byte[70];byte[] byID = new byte[36];byte[] byCompany = new byte[30];byte[] byBeginDate = new byte[16];byte[] byEndDate = new byte[16];System.arraycopy(pucCHMsg, 0, byName, 0, 30);System.arraycopy(pucCHMsg, 30, bySex, 0, 2);System.arraycopy(pucCHMsg, 32, byRace, 0, 4);System.arraycopy(pucCHMsg, 36, byBirth, 0, 16);System.arraycopy(pucCHMsg, 52, byAddress, 0, 70);System.arraycopy(pucCHMsg, 122, byID, 0, 36);System.arraycopy(pucCHMsg, 158, byCompany, 0, 30);System.arraycopy(pucCHMsg, 188, byBeginDate, 0, 16);System.arraycopy(pucCHMsg, 204, byEndDate, 0, 16);//解析身份证数据IdcordBean idcordBean=new IdcordBean();try {System.out.println(Arrays.toString(byName));System.out.println(Arrays.toString(byCompany));System.out.println(Arrays.toString(byAddress));byte[] namebytes=toByte(byName);byte[] companyBytes=toByte(byCompany);byte[] addressbytes=toByte(byAddress);String name = new String(namebytes, "UNICODE");String company = new String(companyBytes, "UNICODE");String address = new String(addressbytes, "UNICODE");idcordBean.setByName(name).setByCompany(company).setByAddress(address);//打印身份证信息System.out.println(name);System.out.println(company);System.out.println(address);} catch (UnsupportedEncodingException e) {e.printStackTrace();}idcordBean.setBySex(new String(bySex).replaceAll("\\u0000","")).setByID(new String(byID).replaceAll("\\u0000","")).setByRace(new String(byRace).replaceAll("\\u0000","")).setByBirth(new String(byBirth).replaceAll("\\u0000","")).setByBeginDate(new String(byBeginDate).replaceAll("\\u0000","")).setByEndDate(new String(byEndDate).replaceAll("\\u0000",""));
//            System.out.println(new String(bySex));
//            System.out.println(new String(byRace));
//            System.out.println(new String(byBirth));
//            System.out.println(new String(byID));
//            System.out.println(new String(byBeginDate));
//            System.out.println(new String(byEndDate));return idcordBean;}

注意:我的设备读取出来的身份证设备的汉字的字节码需要进行转换,我提供一下我的汉字编码信息(姓名,发证机关,住址,有兴趣的可以进行解码试试),汉字编码是 UNICODE编码,其他信息将 UNICODE编码的空格给替换掉  "".replaceAll("\\u0000","")

[115, -105, 122, 102, 58, 95, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0]
[-26, 121, -119, 91, -65, 83, 108, 81, -119, 91, 64, 92, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0]
[24, 117, -125, -128, 1, 119, -26, 121, -119, 91, -65, 83, -10, 83, 33, 88, 71, -107, -80, 101, 84, -128, 81, 103, 50, 0, -9, 83, -13, 119, -126, -126, -60, 126, 18, -1, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0]

解码方法:

//身份证汉字编码解码public static byte[] toByte(byte [] source){int length=0;for (int i = 0; i < source.length; i++) {if(source[i]==32&&source[i+1]==0){length=i;break;}}System.out.println(length);byte[] obj=new byte[length+2];obj[0]=-2;obj[1]=-1;for (int i = 0; i < length; i++) {if(i%2==0){obj[i+3]=source[i];}else{obj[i+1]=source[i];}}return obj;}

最后给一份完整的代码

public class UsbIdCordRead {//    public static final String dllPath="D:\\java\\dll\\";public static final String dllPath="";public static final int port=1001;public interface CLibrary extends Library {// sdtapi.dll 32位的包,开发过程切换到32位的jdk运行,CLibrary INSTANCE = (CLibrary) Native.load(dllPath+"sdtapi", CLibrary.class);//读取身份证信息 使用到如下方法int SDT_OpenPort(int iPort);int SDT_StartFindIDCard( int iPort,byte[] a,int iIfOpen );int SDT_ReadBaseFPMsg( int iPort ,byte[] pucCHMsg ,IntByReference puiCHMsgLen ,byte[] pucPHMsg ,IntByReference puiPHMsgLen,byte[] pucFPMsg,IntByReference puiFMsgLen,int iIfOpen );int SDT_SelectIDCard( int iPort ,byte[] a,int iIfOpen);int SDT_ReadBaseMsg(int iPort ,byte[] pucCHMsg ,IntByReference puiCHMsgLen ,byte[] pucPHMsg ,IntByReference puiPHMsgLen,int iIfOpen  );int SDT_GetSAMIDToStr( int iPort,byte[] strSAMID ,int iIfOpen );}/*** 读取身份证信息:返回为空表示读取失败* @return*/public static synchronized IdcordBean readIdCord(){//打开端口int value = CLibrary.INSTANCE.SDT_OpenPort(port);System.out.println(Integer.toHexString(value));byte[] strSAMID = new byte[65] ;int samid= CLibrary.INSTANCE.SDT_GetSAMIDToStr(port, strSAMID,1);System.out.println("读取samid:"+Integer.toHexString(samid));String s = new String(strSAMID);System.out.println(s);byte[] bytes = new byte[16];//查找身份证int select = CLibrary.INSTANCE.SDT_StartFindIDCard(port, bytes,1);System.out.println("寻卡:"+Integer.toHexString(select));String s1 = new String(bytes);System.out.println(s1);//选卡int selectCode= CLibrary.INSTANCE.SDT_SelectIDCard(port, bytes,1);System.out.println("选卡:"+Integer.toHexString(selectCode));String s2 = new String(bytes);System.out.println(s2);byte[] pucCHMsg=new byte[256 + 1] ,pucPHMsg=new byte[1024 + 1],pucFPMsg=new byte[1024 + 1];IntByReference puiCHMsgLen=new IntByReference(0) , puiPHMsgLen=new IntByReference(0),puiFMsgLen=new IntByReference(0);//第一次读卡,带指纹的
//        int readOld= CLibrary.INSTANCE.SDT_ReadBaseFPMsg(port, pucCHMsg,puiCHMsgLen,pucPHMsg,puiPHMsgLen,pucFPMsg,puiFMsgLen,1);
//        System.out.println("读卡1:"+Integer.toHexString(readOld)+":");//第二次读卡,不带指纹int read= CLibrary.INSTANCE.SDT_ReadBaseMsg(port, pucCHMsg,puiCHMsgLen,pucPHMsg,puiPHMsgLen,1);System.out.println("读卡2:"+Integer.toHexString(read)+":");if(Integer.toHexString(read).equals(90+"")){byte[] byName = new byte[30];byte[] bySex = new byte[2];byte[] byRace = new byte[4];byte[] byBirth = new byte[16];byte[] byAddress = new byte[70];byte[] byID = new byte[36];byte[] byCompany = new byte[30];byte[] byBeginDate = new byte[16];byte[] byEndDate = new byte[16];System.arraycopy(pucCHMsg, 0, byName, 0, 30);System.arraycopy(pucCHMsg, 30, bySex, 0, 2);System.arraycopy(pucCHMsg, 32, byRace, 0, 4);System.arraycopy(pucCHMsg, 36, byBirth, 0, 16);System.arraycopy(pucCHMsg, 52, byAddress, 0, 70);System.arraycopy(pucCHMsg, 122, byID, 0, 36);System.arraycopy(pucCHMsg, 158, byCompany, 0, 30);System.arraycopy(pucCHMsg, 188, byBeginDate, 0, 16);System.arraycopy(pucCHMsg, 204, byEndDate, 0, 16);//解析身份证数据IdcordBean idcordBean=new IdcordBean();try {System.out.println(Arrays.toString(byName));System.out.println(Arrays.toString(byCompany));System.out.println(Arrays.toString(byAddress));byte[] namebytes=toByte(byName);byte[] companyBytes=toByte(byCompany);byte[] addressbytes=toByte(byAddress);String name = new String(namebytes, "UNICODE");String company = new String(companyBytes, "UNICODE");String address = new String(addressbytes, "UNICODE");idcordBean.setByName(name).setByCompany(company).setByAddress(address);//打印身份证信息System.out.println(name);System.out.println(company);System.out.println(address);} catch (UnsupportedEncodingException e) {e.printStackTrace();}idcordBean.setBySex(new String(bySex).replaceAll("\\u0000","")).setByID(new String(byID).replaceAll("\\u0000","")).setByRace(new String(byRace).replaceAll("\\u0000","")).setByBirth(new String(byBirth).replaceAll("\\u0000","")).setByBeginDate(new String(byBeginDate).replaceAll("\\u0000","")).setByEndDate(new String(byEndDate).replaceAll("\\u0000",""));
//            System.out.println(new String(bySex));
//            System.out.println(new String(byRace));
//            System.out.println(new String(byBirth));
//            System.out.println(new String(byID));
//            System.out.println(new String(byBeginDate));
//            System.out.println(new String(byEndDate));return idcordBean;}return null;}//身份证汉字编码解码public static byte[] toByte(byte [] source){int length=0;for (int i = 0; i < source.length; i++) {if(source[i]==32&&source[i+1]==0){length=i;break;}}System.out.println(length);byte[] obj=new byte[length+2];obj[0]=-2;obj[1]=-1;for (int i = 0; i < length; i++) {if(i%2==0){obj[i+3]=source[i];}else{obj[i+1]=source[i];}}return obj;}public static void main(String[] args) {readIdCord();}
}

java调用sdtapi.dll读取身份证设备信息的一次记录相关推荐

  1. c#使用wpd读取便携式设备信息二

    在上节内容(c#使用wpd读取便携式设备信息一)中,我们已经获取到了设备名称,容量等信息,本节进行读写设备的存储内容操作.WPD对设备的操作都是基于对象的ID的,例如文件夹和文件都有各自的object ...

  2. Java调用第三方dll

    刚接触Java几天,项目需要,使用Java调用can卡的dll,发现网上的帖子有很多不明确的地方,特此写之. 首先安装开发环境,考虑到兼容性,安装的JDK和eclipse都是32位的,正常安装结束后, ...

  3. C# 制作Com组件:java调用.net DLL的方法

    本文将详细为大家介绍一个java调用.net DLL的方法,以实现特殊的客户的特殊要求:"在Java项目中必须使用其提供的用.net写的DLL加密机制!" 环境与工具: ◆.net ...

  4. Android NFC源码读取公交卡信息余额和交易记录

    通过NFC的读模式,读取公交卡的余额和交易记录.可以读取深圳通.羊城通.北京卡.八达通.武汉通等. 源码亲测可用放心下载. 源码下载Eclipse版本:Android NFC源码读取公交卡信息余额和交 ...

  5. c#使用WPD读取便携式设备信息一(枚举设备、连接设备及读取设备信息)

    手机或其他电子设备通过USB插入电脑上,并且以MTP(媒体传输协议)方式连接时,可在"计算机"中看到类似计算机盘符的便携式设备文件夹显示,但是这并不是一个计算机盘符,并不能通过常规 ...

  6. java调用c dll,指针参数和结构体参数搞定

    基于上两篇java调用dll的文章,我做了更为复杂的参数传递,指针变量和结构体变量,下面给出源码 vc++中的工程名称是SMSXIAO Source Files(源文件):.c文件名:sms.c 源码 ...

  7. java调用C++ DLL库方法

    转载地址: https://www.cnblogs.com/xiaocainiao2hao/p/5619862.html 最近一个项目要开发网页端人脸识别项目,人脸识别的算法已经写好,是C++版,但是 ...

  8. java 调用 .net dll_c# – 如何从Java调用.NET dll

    我有这个代码来创建一个简单的.NET .dll.它只返回一个int. 但是,它不适用于Java. using System; using System.Collections.Generic; usi ...

  9. 通过阿里云API 身份证图片或拍身份证 读取身份证正反面信息

    参看文:阿里的资料 https://market.aliyun.com/products/57124001/cmapi010401.html?spm=5176.8243888.554823.2.wXf ...

最新文章

  1. Matplot pyplot绘制单图,多子图不同样式详解,这一篇就够了
  2. 优秀PHP在线教程收集
  3. FPGA逻辑设计回顾(8)单比特信号的CDC处理方式之Toggle同步器
  4. 500 OOPS:cannot change directory:/root 问题
  5. 12、INNER JOIN:内连接
  6. mysql采用 级触发_Mysql高级之触发器(trigger)
  7. 37 CO配置-控制-产品成本控制-成本对象控制-实际成本核算/物料分类帐-分配货币类型并定义物料分类账类型
  8. 零距离泛目录站群开源版源码
  9. html报告怎么发送给别人,如何将由Html-test runner(.html)生成的报告通过电子邮件发送给特定用户?...
  10. NSArray 数组
  11. 编译原理三大经典书籍
  12. 案例 | 上海移动:数字化通向互联网的三个路标
  13. 软件产品案例分析(团队)
  14. 计算机视觉论文-2021-09-09
  15. 记一次react项目部署之后页面加载极度缓慢的问题
  16. C++在使用fgetc读取文件时出现方框乱码
  17. 关于游戏中的数据分析
  18. springboot启动报Field sysModuleService in demo.snow.manager.SysModuleController required a bean of type
  19. 微信小程序 虚拟现实_开发虚拟现实应用程序的重要性
  20. 用nodejs配合python破解X-Ca-Signature,抓取博客积分数据

热门文章

  1. 两个div滚动条同步简单实现
  2. 史上最全 Python 爬虫工具列表大全,赶快收藏一波
  3. 计算机考试ASP题目怎么做,ASP学生考试系统
  4. JS中三个点(...)
  5. console常用的方法
  6. ad域 禁用账号_AD域策略如何限制软件运行
  7. textarea没有value属性
  8. 苹果欲收购东芝闪存 自己把控闪存技术
  9. 触动心弦的职场小故事
  10. 内存泄漏,关于异步回调导致的内存泄漏,使用LeakCanary检测内存泄漏