客户提供一台读卡器、sdtapi.dll、WltRS.dll,以及相应的头文件,我是通过java的jni与所写c++代码进行交互,但是java这边接收到的身份证基本信息一直是乱码。先说明c++向java传其他中文不会出现乱码,是在c++读出的身份证信息就是乱码。c++的代码如下:
#include "windows.h"
#include "CardReader.h"
#include "sdtapi.h"
#include "String.h"
#include "WltRS.h"
JNIEXPORT jbyteArray JNICALL Java_CardReader_getMessage(JNIEnv * env, jobject jobj){
char* szStr="mei zhao dao xin xi";
char cInput;
int iRet; //返回码
int iPort; //端口号
int iIfOpen=0; //是否需要打开串口
unsigned char pucIIN[8];
unsigned char pucSN[8];
unsigned char pucCHMsg[512]; //文字信息
unsigned char pucPHMsg[1024]; //照片信息
unsigned char pucFPMsg[1024]; //指纹信息
unsigned int uiCHMsgLen,uiPHMsgLen; memset(pucCHMsg,0,sizeof(pucCHMsg));
int length;
jbyteArray RtnArr = NULL;
jsize arrsize;
if(iIfOpen==0){
for (iPort = 1001; iPort <= 1016; iPort++)
{
iRet=SDT_OpenPort(iPort);
printf("SDT_OpenPort usb error, error code is: %02x\n", iRet);
printf("SDT_OpenPort usb error, error code is: %02d\n", iPort);
if(iRet==0x90) break;
}
if(iRet!=0x90)
{
printf("SDT_OpenPort error, error code is: %02x\n", iRet);
SDT_ClosePort(iPort);
szStr="SDT_OpenPort error";
printf(szStr);
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;
}
iRet=SDT_StartFindIDCard(iPort,pucIIN, iIfOpen);
printf("SDT_StartFindIDCard error, error code is: %02x\n", iRet);
if (iRet != 0x9f)
{
iRet=SDT_StartFindIDCard(iPort,pucIIN, iIfOpen); //再找卡
if (iRet != 0x9f)
{
iRet = SDT_ClosePort(iPort);
printf("SDT_StartFindIDCard error, error code is: %02x\n", iRet);
szStr="SDT_StartFindIDCard error";
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;
}
}
iRet=SDT_SelectIDCard (iPort,pucSN, iIfOpen);
printf("SDT_SelectIDCard error, error code is: %02x\n", iRet);
if (iRet != 0x90)
{
iRet=SDT_SelectIDCard (iPort,pucSN, iIfOpen); //再选卡
if (iRet != 0x90)
{
iRet = SDT_ClosePort(iPort);
printf("SDT_SelectIDCard error, error code is: %02x\n", iRet);
szStr="SDT_SelectIDCard error";
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;
}
}
iRet=SDT_ReadBaseMsg(iPort,pucCHMsg,&uiCHMsgLen, pucPHMsg,&uiPHMsgLen, iIfOpen);
printf("SDT_ReadBaseMsg error, error code is: %02x\n", iRet);
if(iRet!=0x90)
{
printf("SDT_ReadBaseMsg error, error code is: %02x\n", iRet);
if(iIfOpen==0)
SDT_ClosePort(iPort);
printf("ssaaaasasasaas\n");
szStr="SDT_ReadBaseMsg error";
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
printf("123345453\n");
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
printf("12sssssssss33454534ssaaaasasasaas");
return RtnArr;
}
printf("SDT_ReadBaseMsg OK\n");
if(iIfOpen==0)
SDT_ClosePort(iPort); RtnArr=env->NewByteArray(uiCHMsgLen);
printf("pucCHMsg=%s\n",pucCHMsg);
env->SetByteArrayRegion(RtnArr, 0,uiCHMsgLen, (jbyte*)pucCHMsg);
return RtnArr;
} length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;}
#include "windows.h"
#include "CardReader.h"
#include "sdtapi.h"
#include "String.h"
#include "WltRS.h"
JNIEXPORT jbyteArray JNICALL Java_CardReader_getMessage(JNIEnv * env, jobject jobj){
char* szStr="mei zhao dao xin xi";
char cInput;
int iRet; //返回码
int iPort; //端口号
int iIfOpen=0; //是否需要打开串口
unsigned char pucIIN[8];
unsigned char pucSN[8];
unsigned char pucCHMsg[512]; //文字信息
unsigned char pucPHMsg[1024]; //照片信息
unsigned char pucFPMsg[1024]; //指纹信息
unsigned int uiCHMsgLen,uiPHMsgLen; memset(pucCHMsg,0,sizeof(pucCHMsg));
int length;
jbyteArray RtnArr = NULL;
jsize arrsize;
if(iIfOpen==0){
for (iPort = 1001; iPort <= 1016; iPort++)
{
iRet=SDT_OpenPort(iPort);
printf("SDT_OpenPort usb error, error code is: %02x\n", iRet);
printf("SDT_OpenPort usb error, error code is: %02d\n", iPort);
if(iRet==0x90) break;
}
if(iRet!=0x90)
{
printf("SDT_OpenPort error, error code is: %02x\n", iRet);
SDT_ClosePort(iPort);
szStr="SDT_OpenPort error";
printf(szStr);
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;
}
iRet=SDT_StartFindIDCard(iPort,pucIIN, iIfOpen);
printf("SDT_StartFindIDCard error, error code is: %02x\n", iRet);
if (iRet != 0x9f)
{
iRet=SDT_StartFindIDCard(iPort,pucIIN, iIfOpen); //再找卡
if (iRet != 0x9f)
{
iRet = SDT_ClosePort(iPort);
printf("SDT_StartFindIDCard error, error code is: %02x\n", iRet);
szStr="SDT_StartFindIDCard error";
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;
}
}
iRet=SDT_SelectIDCard (iPort,pucSN, iIfOpen);
printf("SDT_SelectIDCard error, error code is: %02x\n", iRet);
if (iRet != 0x90)
{
iRet=SDT_SelectIDCard (iPort,pucSN, iIfOpen); //再选卡
if (iRet != 0x90)
{
iRet = SDT_ClosePort(iPort);
printf("SDT_SelectIDCard error, error code is: %02x\n", iRet);
szStr="SDT_SelectIDCard error";
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;
}
}
iRet=SDT_ReadBaseMsg(iPort,pucCHMsg,&uiCHMsgLen, pucPHMsg,&uiPHMsgLen, iIfOpen);
printf("SDT_ReadBaseMsg error, error code is: %02x\n", iRet);
if(iRet!=0x90)
{
printf("SDT_ReadBaseMsg error, error code is: %02x\n", iRet);
if(iIfOpen==0)
SDT_ClosePort(iPort);
printf("ssaaaasasasaas\n");
szStr="SDT_ReadBaseMsg error";
length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
printf("123345453\n");
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
printf("12sssssssss33454534ssaaaasasasaas");
return RtnArr;
}
printf("SDT_ReadBaseMsg OK\n");
if(iIfOpen==0)
SDT_ClosePort(iPort); RtnArr=env->NewByteArray(uiCHMsgLen);
printf("pucCHMsg=%s\n",pucCHMsg);
env->SetByteArrayRegion(RtnArr, 0,uiCHMsgLen, (jbyte*)pucCHMsg);
return RtnArr;
} length = strlen(szStr);
arrsize =(jsize)length;
RtnArr=env->NewByteArray(arrsize);
env->SetByteArrayRegion(RtnArr, 0,length, (jbyte*)szStr);
return RtnArr;}
Wine軟件包模擬Windows環境
因为二代身份证里编码为GB13000,在java处理中存在问题,总体处理思想为先把16进制字节高地位互换,然后用UTF-16BE转换成中文字符代码如下
public static String hexByes2String(byte[] bytes,String charsetName){
if("".equals(charsetName)) charsetName="UTF-16BE";
try {
return new String(bytes,charsetName);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
public static byte[] hexBytesH2L(byte[] bytes)
{
byte tmp = 0;
for(int i=0;i<bytes.length;i++){
if(i%2==0) {
tmp=bytes[i];
bytes[i]=bytes[i+1];
}
else bytes[i]=tmp;
}
return bytes;
}
调用:hexByes2String(XSocketUtils.hexBytesH2L(hexBytes),"UTF-16BE")
图片信息处理(用到jna.jar包)
图片信息处理必须调用第三方提供dll,GETINFO.DLL,过程是先在java中保存16进制字节为一个wlt文件在用GETINFO.DLL中的getBMP函数,生成bmp图片,在从bmp提取图片字节,函数如下(直接调用getPictureBytes即可)import com.sun.jna.Library;
import com.sun.jna.Native;public class GetSFZPic {
public interface CLibrary extends Library {
CLibrary wltToBmp = (CLibrary) Native.loadLibrary("GETINFO",CLibrary.class);
void GetBmp(String wltfile,int a);
}
private static void generatePictureBmp(byte[] picbytes,String idcard){
try {
String wltfile=System.getProperty( "user.dir")+"\\shxxcjxtzp.wlt";
if(null!=picbytes){
DataOutputStream out=new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(wltfile)));
out.write(picbytes);
out.close();
}
CLibrary.wltToBmp.GetBmp(wltfile, 1);
} catch (IOException e) {
e.printStackTrace();
} }
public synchronized static byte[] getPictureBytes(byte[]picbytes,String idcard) { String filename=System.getProperty( "user.dir")+"\\shxxcjxtzp.bmp";
generatePictureBmp(picbytes,idcard);
File file =new File(filename);
if(filename==null || filename.equals("")) {
throw new NullPointerException("无效的文件路径");
}
long len = file.length();
byte[] bytes = new byte[(int)len];
System.out.println(filename+"--------"+len);
BufferedInputStream bufferedInputStream;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
int r = bufferedInputStream.read( bytes );
if (r != len)
throw new IOException("读取文件不正确");
bufferedInputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bytes; }
}