糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > java调用sdtapi.dll读取身份证设备信息的一次记录

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

时间:2022-03-23 11:27:36

相关推荐

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

前端时间写项目写到了排队项目,需要用到身份证读取功能,但是市面找了很久发现读取身份证的基本没有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读取身份证设备信息的一次记录》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。