Java Jna调DLL函数读写15693卡

import com.sun.jna.Library ;
import com.sun.jna.Native;

interface CLibrary extends Library {
    //DLL绝对路径的地址获取,注意要去空格,特别坑
    //不同版本的读写器,接口DLL文件名称、函数名称是一样的,但内核代码不一样,请选用与读写器、操作系统一致的OUR_MIFARE.dll
    String filePath = CLibrary.class.getResource("").getPath().replaceFirst("/","").replaceAll("%20"," ")+"OUR_MIFARE";
    CLibrary sdtapi = (CLibrary) Native.loadLibrary(filePath, CLibrary.class);

    //动态链接库中的方法
    byte pcdbeep(int xms);                         //让设备发出声音
    byte pcdgetdevicenumber(byte[] devicenumber);  //读取设备编号
    byte iso15693readex(byte ctrlword,byte afi,byte startblock,byte blocknum,byte[] mypiccserial,byte[] piccdata);    //轻松读卡,读出卡号及从某块开始的N块信息
    byte iso15693writeex(byte ctrlword,byte afi,byte startblock,byte blocknum,byte[] mypiccserial,byte[] piccdata);   //轻松写卡,写数据到在感应区的卡的从某块开始的N块中
    //以上方法可以完成绝大部份应用需求,
    byte iso15693inventory(byte flags,byte afi,byte masklen,byte[] maskuidbuf,byte[] mypiccserial);                   //寻单卡(感应区只能一张卡)
    byte iso15693inventory16(byte flags,byte afi,byte masklen,byte[] maskuidbuf,byte[] revlen,byte[] mypiccserial);   //寻在感应区中的多张卡
    byte iso15693stayquiet(byte flags,byte[] mypiccserial);       //使卡片静止休眠
    byte iso15693resettoready(byte flags,byte[] mypiccserial);    //让卡从静止中重启
    byte iso15693Select(byte flags,byte[] mypiccserial);          //选择卡片
    byte iso15693readblock(byte flags,byte startblock,byte blocknum,byte[] mypiccserial,byte[] revlen,byte[] piccdata);     //读取指定卡号的卡片块内数据
    byte iso15693writeblock(byte flags,byte startblock,byte blocknum,byte[] mypiccserial,byte writelen,byte[] piccdata);    //写数据到指定卡号的块内
    //危险函数
    byte iso15693writeafi(byte flags,byte afi,byte[] mypiccserial);    //写AFI
    byte iso15693lockafi(byte flags,byte[] mypiccserial);              //锁AFI
    byte iso15693writedsfid(byte flags,byte dsfid,byte[] mypiccserial);          //写DSFID 指令
    byte iso15693lockdsfid(byte flags,byte[] mypiccserial);                      //锁DSFID 指令
}

public class ReadWrite15693 {

    public static void main(String[] args) {
        System.setProperty("jna.encoding", "GBK");

        if (args.length == 0) {
            System.out.println("请先输入运行参数!");
            System.out.println("\n参数 0:驱动读卡器嘀一声");
            System.out.println("\n参数 1:读取设备编号");
            System.out.println("\n参数 2:轻松读卡,读出卡号及从某块开始的N块信息");
            System.out.println("\n参数 3:轻松写卡,写数据到在感应区的卡的从某块开始的N块中");
            System.out.println("\n参数 4:搜寻感应区内单张15693卡(感应区只能一张卡)");
            System.out.println("\n参数 5:搜寻在感应区中的多张15693卡");
            System.out.println("\n参数 6:使卡片静止休眠");
            System.out.println("\n参数 7:让卡从静止中重启");
            System.out.println("\n参数 8:选中指定的15693卡");
            System.out.println("\n参数 9:读取指定卡号的卡片块内数据");
            System.out.println("\n参数 10:写数据到指定卡序号的卡片内");
            return;
        }

        //Java中只能使用string1.equals(string2)的方式来比较字符串
        if (args[0].equals("0")) {             //驱动读卡器发嘀一声
            System.out.print("\n0-驱动读卡器嘀一声\n");
            CLibrary.sdtapi.pcdbeep(50);
            System.out.print("结果:如果能听到读卡器嘀一声表示成功,否则请检查读卡器是否已连上线!\n\n");

        } else if (args[0].equals("1"))          //读取设备编号,可做为软件加密狗用,也可以根据此编号在公司网站上查询保修期限
        {
            int status;                          //存放返回值
            byte[] devicenumber = new byte[4];   //4字节设备编号

            status = (int) (CLibrary.sdtapi.pcdgetdevicenumber(devicenumber) & 0xff);//& 0xff用于转为无符号行数据
            System.out.print("\n1-读取设备编号\n");
            System.out.print("结果:");
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                System.out.print("读取成功!设备编号为" + (devicenumber[0] & 0xff) + "-" + (devicenumber[1] & 0xff) + "-" + (devicenumber[2] & 0xff) + "-" + (devicenumber[3] & 0xff));
                System.out.print("\n\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        } else if (args[0].equals("2")) {     //轻松读卡,读出卡号及从某块开始的N块信息
            int status;                       //存放返回值
            byte myctrlword = 0;              //读写控制字,一般取0 就行了
            byte afi = 0;                     //卡片应用标识
            byte startblock = 0;              //指定读起始块地址,最大取值255(根据卡类型)
            byte blocknum = 12;               //指定读取块数,最大取值12
            byte[] myuid = new byte[8];       //8字节卡序列号缓冲
            byte[] mydatabuf = new byte[255]; //读卡数据缓冲共255个字节

            status = (int) (CLibrary.sdtapi.iso15693readex(myctrlword, afi, startblock, blocknum, myuid, mydatabuf) & 0xff);
            System.out.print("\n2-轻松读15693卡\n");
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读卡成功,卡序列号:" + serialnumber+"\n");

                String databuf = "";
                for (int i = 1; i < mydatabuf[0]+1; i++) {
                    String bytestr = "00" + Integer.toHexString(mydatabuf[i] & 0xff);
                    databuf = databuf + bytestr.substring(bytestr.length() - 2, bytestr.length())+" ";
                }
                System.out.print("卡内数据:" + databuf +"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        } else if (args[0].equals("3")) {         //轻松写卡,写数据到在感应区的卡的从某块开始的N块中,同时返回卡号
            int status;                            //存放返回值
            byte myctrlword = 0;                   //读写控制字,一般取0 就行了
            byte afi = 0;                          //卡片应用标识
            byte startblock = 0;                   //指定写起始块地址,最大取值255(根据卡类型)
            byte blocknum = 12;                    //指定写块数,最大取值12
            byte writeBufLen=(byte)(blocknum*4);   //写入数据长度,每块4个字节
            byte[] myuid = new byte[8];            //8字节卡序列号缓冲
            byte[] WriteBuf = new byte[48];        //写卡缓冲,

            WriteBuf[0]=writeBufLen;                //写卡缓冲的第一个字节是本次要写入的长度
            //写中文或字母数字等字符信息,将要写入的字符转ASCII码写入
            String WriteStr = "伟大的中华人民共和国万岁!1949-10-01                                "; //将要写入的文字生成字节数组
            byte[] strbuf = WriteStr.getBytes();
            for (int i = 0; i < 47; i++) {           //指定写卡数据,最长47个字节,其中首字节是写信息的长度
                WriteBuf[i+1] = strbuf[i];
            }

            status = (int) (CLibrary.sdtapi.iso15693writeex(myctrlword, afi, startblock, blocknum, myuid, WriteBuf) & 0xff);
            System.out.print("\n3-轻松写15693卡\n");
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("写卡成功,卡序列号:" + serialnumber+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        }else if (args[0].equals("4")) {           //寻单卡(感应区只能一张卡)
            int status;                            //存放返回值
            byte afi = 0;                          //卡片应用标识
            byte flags = (byte) 0x36;              //操作卡片的标识字,详细说明参看文档
            byte masklen = 0;                      //掩码长度,有一张卡最大为40,一张卡为43,理论上为64
            byte[] maskuidbuf = new byte[8];       //卡号掩码,一般可以不理这个参数
            byte[] myuid = new byte[9];           //9字节卡数据缓冲

            System.out.print("\n4-搜寻感应区内单张15693卡(感应区只能一张卡)\n");
            status = (int) (CLibrary.sdtapi.iso15693inventory(flags, afi, masklen, maskuidbuf, myuid) & 0xff);
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String bytestr = "00" + Integer.toHexString(myuid[0] & 0xff);
                System.out.print("DSFID:" + bytestr.substring(bytestr.length() - 2, bytestr.length())+"\n");

                String serialnumber = "";
                for (int i = 1; i < 9; i++) {
                    bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("卡序列号UID:" + serialnumber+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        }else if (args[0].equals("5")) {           //搜寻在感应区中的多张15693卡
            int status;                            //存放返回值
            byte afi = 0;                          //卡片应用标识
            byte flags = (byte) 0x16;              //操作卡片的标识字,详细说明参看文档
            byte masklen = 0;                      //掩码长度,有一张卡最大为40,一张卡为43,理论上为64
            byte[] maskuidbuf = new byte[8];       //卡号掩码,一般可以不理这个参数
            byte[] myuid = new byte[81];           //卡数据缓冲
            byte[] revlen= new byte[1];

            System.out.print("\n5-搜寻感应区内多张15693卡\n");
            status = (int) (CLibrary.sdtapi.iso15693inventory16(flags, afi, masklen, maskuidbuf, revlen,myuid) & 0xff);
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                int j=0;
                while (j<revlen[0]) {
                    String bytestr = "00" + Integer.toHexString(myuid[j] & 0xff);
                    System.out.print("DSFID:" + bytestr.substring(bytestr.length() - 2, bytestr.length()) + "\n");

                    String serialnumber = "";
                    for (int i = 1; i < 9; i++) {
                        bytestr = "00" + Integer.toHexString(myuid[j+i] & 0xff);
                        serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                    }
                    System.out.print("卡序列号UID:" + serialnumber + "\n\n");
                    j=j+9;
                }
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        } else if (args[0].equals("6")) {          //使卡片静止休眠,静止的卡iso15693inventory指令及iso15693inventory16指令搜寻不到
            int status;                            //存放返回值
            byte flags = (byte) 0x22;              //操作卡片的标识字,详细说明参看文档
            byte[] myuid = new byte[8];            //指定要休眠卡的UID

            myuid[0]=(byte) 0xbe;  //8字节要休眠卡的UID
            myuid[1]=(byte) 0x9d;
            myuid[2]=(byte) 0x00;
            myuid[3]=(byte) 0x6b;
            myuid[4]=(byte) 0x00;
            myuid[5]=(byte) 0x01;
            myuid[6]=(byte) 0x04;
            myuid[7]=(byte) 0xe0;

            System.out.print("\n6-将感应区上的卡休眠\n");
            status = (int) (CLibrary.sdtapi.iso15693stayquiet(flags, myuid) & 0xff);
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("已静止休眠UID:" + serialnumber+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        } else if (args[0].equals("7")) {          //让卡从静止中重启
            int status;                            //存放返回值
            byte flags = (byte) 0x22;              //操作卡片的标识字,详细说明参看文档
            byte[] myuid = new byte[8];            //指定已休眠要重新启用卡的UID

            myuid[0]=(byte) 0xbe;  //8字节要重新启用卡的UID
            myuid[1]=(byte) 0x9d;
            myuid[2]=(byte) 0x00;
            myuid[3]=(byte) 0x6b;
            myuid[4]=(byte) 0x00;
            myuid[5]=(byte) 0x01;
            myuid[6]=(byte) 0x04;
            myuid[7]=(byte) 0xe0;

            System.out.print("\n7-让卡从静止中重启\n");
            status = (int) (CLibrary.sdtapi.iso15693resettoready(flags, myuid) & 0xff);
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("已重启卡UID:" + serialnumber+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        } else if (args[0].equals("8")) {          //选择卡片
            int status;                            //存放返回值
            byte flags = (byte) 0x22;              //操作卡片的标识字,详细说明参看文档
            byte[] myuid = new byte[8];            //指定已休眠要重新启用卡的UID

            myuid[0]=(byte) 0xbe;  //8字节要重新启用卡的UID
            myuid[1]=(byte) 0x9d;
            myuid[2]=(byte) 0x00;
            myuid[3]=(byte) 0x6b;
            myuid[4]=(byte) 0x00;
            myuid[5]=(byte) 0x01;
            myuid[6]=(byte) 0x04;
            myuid[7]=(byte) 0xe0;

            System.out.print("\n8-选择卡片");
            status = (int) (CLibrary.sdtapi.iso15693Select(flags, myuid) & 0xff);
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("\n已选择卡UID:" + serialnumber+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        }else if (args[0].equals("9")) {      //读取指定卡号的卡片块内数据
            int status;                       //存放返回值
            byte flags = (byte) 0x22;         //操作卡片的标识字,详细说明参看文档
            byte startblock = 0;              //指定读起始块地址,最大取值255(根据卡类型)
            byte blocknum = 12;               //指定读取块数,最大取值12
            byte[] myuid = new byte[8];       //8字节卡序列号缓冲
            byte[] revlen = new byte[1];      //返回读取数据长度
            byte[] mydatabuf = new byte[255]; //读卡数据缓冲共255个字节

            myuid[0]=(byte) 0xbe;  //8字节要读卡的UID
            myuid[1]=(byte) 0x9d;
            myuid[2]=(byte) 0x00;
            myuid[3]=(byte) 0x6b;
            myuid[4]=(byte) 0x00;
            myuid[5]=(byte) 0x01;
            myuid[6]=(byte) 0x04;
            myuid[7]=(byte) 0xe0;

            status = (int) (CLibrary.sdtapi.iso15693readblock( flags, startblock, blocknum, myuid,revlen, mydatabuf) & 0xff);
            System.out.print("\n9-读取指定卡号的卡片块内数据\n");
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读卡成功,卡序列号:" + serialnumber+"\n");

                String databuf = "";
                int j=0;
                while(j<revlen[0]){
                    String bytestr = "00" + Integer.toHexString(mydatabuf[j] & 0xff);
                    databuf = databuf + bytestr.substring(bytestr.length() - 2, bytestr.length())+" ";
                    j=j+1;
                }
                System.out.print("卡内数据:" + databuf +"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }

        }else if (args[0].equals("10")) {     //写数据到指定卡序号的卡片内
            int status;                       //存放返回值
            byte flags = (byte) 0x22;         //操作卡片的标识字,详细说明参看文档
            byte startblock = 0;              //指定读起始块地址,最大取值255(根据卡类型)
            byte blocknum = 12;               //指定读取块数,最大取值12
            byte[] myuid = new byte[8];       //8字节卡序列号缓冲
            byte writelen = (byte)(blocknum*4); //写数据长度,每个块4个字节
            byte[] mydatabuf = new byte[255]; //读卡数据缓冲共255个字节

            myuid[0]=(byte) 0xbe;  //8字节要写卡的UID
            myuid[1]=(byte) 0x9d;
            myuid[2]=(byte) 0x00;
            myuid[3]=(byte) 0x6b;
            myuid[4]=(byte) 0x00;
            myuid[5]=(byte) 0x01;
            myuid[6]=(byte) 0x04;
            myuid[7]=(byte) 0xe0;

            //写中文或字母数字等字符信息,将要写入的字符转ASCII码写入
            String WriteStr = "伟大的中华人民共和国万岁!1949-10-01                                "; //将要写入的文字生成字节数组
            byte[] strbuf = WriteStr.getBytes();
            for (int i = 0; i < writelen; i++) {           //指定写卡数据,最长48个字节,其中首字节是写信息的长度
                mydatabuf[i] = strbuf[i];
            }

            status = (int) (CLibrary.sdtapi.iso15693writeblock( flags, startblock, blocknum, myuid,writelen, mydatabuf) & 0xff);
            System.out.print("\n10-写数据到指定卡序号的卡片内\n");
            if (status == 0) {
                CLibrary.sdtapi.pcdbeep(38);
                String serialnumber = "";
                for (int i = 0; i < 8; i++) {
                    String bytestr = "00" + Integer.toHexString(myuid[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("写卡成功,卡序列号:" + serialnumber+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }
        }
    }

    //----------------------------------------------------------------------------------错误代码提示
    static void PrintErrInf(int errcode) {
        switch(errcode){
            case 8:
                System.out.print("错误代码:8,未寻到卡,请重新拿开卡后再放到感应区!\n");
                break;
            case 9:
                System.out.print("错误代码:9,有多张卡在感应区,寻卡过程中防冲突失败,读序列吗错误!\n");
                break;
            case 10:
                System.out.print("错误代码:10,该卡可能已被休眠,无法选中卡片!\n");
                break;
            case 13:
                System.out.print("错误代码:13,读卡块失败!\n");
                break;
            case 14:
                System.out.print("错误代码:14,写本块失败!\n");
                break;
            case 21:
                System.out.print("错误代码:21,没有动态库!\n");
                break;
            case 22:
                System.out.print("错误代码:22,动态库或驱动程序异常!\n");
                break;
            case 23:
                System.out.print("错误代码:23,驱动程序错误或尚未安装!\n");
                break;
            case 24:
                System.out.print("错误代码:24,操作超时,一般是动态库没有反映!\n");
                break;
            case 25:
                System.out.print("错误代码:25,发送字数不够!\n");
                break;
            case 26:
                System.out.print("错误代码:26,发送的CRC错!\n");
                break;
            case 27:
                System.out.print("错误代码:27,接收的字数不够!\n");
                break;
            case 28:
                System.out.print("错误代码:28,接收的CRC错!\n");
                break;
            case 41:
                System.out.print("错误代码:41,选中卡操作失败!\n");
                break;
            case 42:
                System.out.print("错误代码:42,让卡从静止中重起准备失败!\n");
                break;
            case 44:
                System.out.print("错误代码:44,一次写块不能超过12块!\n");
                break;
            case 46:
                System.out.print("错误代码:46,写AFI失败!\n");
                break;
            default:
                System.out.print("未知错误,错误代码:"+Integer.toString(errcode)+"\n");
                break;
        }
    }
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 3

打赏作者

津津有味道

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值