java调用zebra斑马打印条码+英文+数字+中文

打印机型号:GT800,只要支持zpl,下面的方式都可以通用。
打印的具体样式如下所示:有引用其他文章的打印方式,但是不通用,而且中文这块,打印出来是反的,并且我需要一次性打印两张一样的,参考的链接百度都是那篇文章,如下:这是原博主的,百度很多都是抄这个一模一样,我在zpl语言那边有改进,具体看下面代码,有详细解析
在这里插入图片描述

先贴上整个类的代码,其中有一个ts24.lib文件我放在网盘,那玩意老费劲不好找,
网盘地址:链接:https://pan.baidu.com/s/1hsPz0F1uBBgg0hlRQDbIfw
提取码:o00d

package com.lims.common.core.utils.print;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.standard.PrinterName;

//import sun.awt.AppContext;
/**
 * 采用点阵字库ts24.lib
 * @author Labrador
 *
 */
public class ZplPrinter {
    private String printerURI = null;			//打印机完整路径
    private PrintService printService = null;	//打印机服务
    private byte[] dotFont;
    private String darkness = "~SD10";	//Set Darkness设置色带颜色的深度 0-30
    private String width = "^PW1000";	//Print Width打印宽度0-1500
    private String length = "^LL800";	//Label Length标签长度0-x(暂无作用)
    private String begin = "^XA" + darkness + width;	//标签格式以^XA开始
    private String end = "^XZ";			//标签格式以^XZ结束
    private String content = "";		//打印内容
    private String message = "";		//打印的结果信息

    /**
     * 构造方法
     * @param printerURI 打印机路径
     */
    public ZplPrinter(String printerURI){
        this.printerURI = printerURI;
        //加载字体
        File file = new File("C:\\Users\\gonghf\\Desktop\\ts24.lib");
        if(file.exists()){
            FileInputStream fis;
            try {
                fis = new FileInputStream(file);
                dotFont = new byte[fis.available()];
                fis.read(dotFont);
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            System.out.println("C://ts24.lib文件不存在");
        }
        //初始化打印机
        //AppContext.getAppContext().put(PrintServiceLookup.class.getDeclaredClasses()[0], null);//刷新打印机列表
        PrintService[] services = PrintServiceLookup.lookupPrintServices(null,null);
        if (services != null && services.length > 0) {
            for (PrintService service : services) {
                if (printerURI.equals(service.getName())) {
                    printService = service;
                    break;
                }
            }
        }
        if (printService == null) {
            System.out.println("没有找到打印机:["+printerURI+"]");
            //循环出所有的打印机
            if (services != null && services.length > 0) {
                System.out.println("可用的打印机列表:");
                for (PrintService service : services) {
                    System.out.println("["+service.getName()+"]");
                }
            }
        }else{
            System.out.println("找到打印机:["+printerURI+"]");
            System.out.println("打印机名称:["+printService.getAttribute(PrinterName.class).getValue()+"]");
        }
    }
    /**
     * 设置条形码
     * @param barcode 条码字符
     * @param zpl 条码样式模板
     */
    public void setBarcode(String barcode,String zpl) {
        content += zpl.replace("${data}", barcode);
    }

    /**
     * 中文字符、英文字符(包含数字)混合
     * @param str 中文、英文
     * @param x x坐标
     * @param y y坐标
     * @param eh 英文字体高度height
     * @param ew 英文字体宽度width
     * @param es 英文字体间距spacing
     * @param mx 中文x轴字体图形放大倍率。范围1-10,默认1
     * @param my 中文y轴字体图形放大倍率。范围1-10,默认1
     * @param ms 中文字体间距。24是个比较合适的值。
     */
    public void setText(String str, int x, int y, int eh, int ew, int es, int mx, float my, int ms) {
        byte[] ch = str2bytes(str);
        for (int off = 0; off < ch.length;) {
            if (((int) ch[off] & 0x00ff) >= 0xA0) {//中文字符
                try {
                    int qcode = ch[off] & 0xff;
                    int wcode = ch[off + 1] & 0xff;
//                    content += String.format("^FO%d,%d^XG0000%01X%01X,%d,%d^FS\n", x, y, qcode, wcode, mx, my);
                    content += String.format("^FO%d,%d^XG0000%01X%01X,%d,%f^FS\n", x, y, qcode, wcode, mx, my);
//                    System.out.println("content===="+content);
                    begin += String.format("~DG0000%02X%02X,00072,003,\n", qcode, wcode);
                    qcode = (qcode + 128 - 32) & 0x00ff;
                    wcode = (wcode + 128 - 32) & 0x00ff;
                    int offset = ((int) qcode - 16) * 94 * 72 + ((int) wcode - 1) * 72;
                    for (int j = 0; j < 72; j += 3) {
                        qcode = (int) dotFont[j + offset] & 0x00ff;
                        wcode = (int) dotFont[j + offset + 1] & 0x00ff;
                        int qcode1 = (int) dotFont[j + offset + 2] & 0x00ff;
                        begin += String.format("%02X%02X%02X\n", qcode, wcode, qcode1);
                    }
                    x =  x + ms * mx;
                    off = off + 2;
                } catch (Exception e) {
                    e.printStackTrace();
                    //替换成X号
                    setChar("X", x, y, eh, ew);
                    x = x + es;//注意间距更改为英文字符间距
                    off = off + 2;
                }
            } else if (((int) ch[off] & 0x00FF) < 0xA0) {//英文字符
                setChar(String.format("%c", ch[off]), x, y, eh, ew);
                x = x + es;
                off++;
            }
        }
    }

    /**
     * 英文字符串(包含数字)
     * @param str 英文字符串
     * @param x	x坐标
     * @param y y坐标
     * @param h 高度  H
     * @param w 宽度
     */
    public void setChar(String str, double x, double y, int h, int w) {
        content += "^FO" + x + "," + y + "^AQN," + h + "," + w + "^FD" + str + "^FS";
    }


    /**
     * 英文字符(包含数字)顺时针旋转180度
     * @param str 英文字符串
     * @param x	x坐标
     * @param y y坐标
     * @param h 高度
     * @param w 宽度
     */
    public void setCharR(String str, int x, int y, int h, int w) {
        content += "^FO" + x + "," + y + "^A0I," + h + "," + w + "^FD" + str + "^FS";
    }
    /**
     * 获取完整的ZPL
     * @return
     */
    public String getZpl() {
        return begin + content + end;
    }

    /**
     * 重置ZPL指令,当需要打印多张纸的时候需要调用。
     */
    public void resetZpl() {
        begin = "^XA" + darkness + width;
        end = "^XZ";
        content = "";
    }
    /**
     * 打印
     * @param zpl 完整的ZPL
     */
    public boolean print(String zpl){
        if(printService==null){
            message = "打印出错:没有找到打印机["+printerURI+"]";
            System.out.println("打印出错:没有找到打印机["+printerURI+"]");
            return false;
        }
        DocPrintJob job = printService.createPrintJob();
        byte[] by = zpl.getBytes();
        DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
        Doc doc = new SimpleDoc(by, flavor, null);
        try {
            job.print(doc, null);
            message = "已打印";
            System.out.println("已打印");
            return true;
        } catch (PrintException e) {
            message = "打印出错:"+e.getMessage();
            System.out.println("打印出错:"+e.getMessage());
            e.printStackTrace();
            return false;
        }
    }
    public String getMessage(){
        return message;
    }
    /**
     * 字符串转byte[]
     * @param s
     * @return
     */
    private byte[] str2bytes(String s) {
        if (null == s || "".equals(s)) {
            return null;
        }
        byte[] abytes = null;
        try {
            abytes = s.getBytes("gb2312");
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }
        return abytes;
    }

    //^B3N,Y,Y  code39条形码
    public  boolean printBarcode(ZplPrinter p){
        //1.打印单个条码
        String bar0 = "D21066000101";//条码内容
        String str = "厦门湖里永康门诊部";
        String bar0Zpl = "^FO190,90^BY1.4,3,80^BCN,60,N,N,N^FD${data}^FS";//条码样式模板
        p.setBarcode(bar0, bar0Zpl);

        p.setCharR(bar0,200,60,25,25);
        content += "^CI26^SEE:GB18030.DAT^CWJ,E:MSUNG24^CI28^FO160,20^A1I,10,10^FD"+str+"^FS";
//        p.setText("厦门湖里永康门诊部", 160, 120, 10, 10, 30, 1, 0, 24);
        content += "^FO500,90^BY1.4,3,80^BCN,60,N,N,N^FD"+bar0+"^FS^FO510,60^A0I,25,25^FD"+bar0+"^FS^FT680,20^A1I,10,10^FD"+str+"^FS";
        String zpl = p.getZpl();
        System.out.println(zpl);
        boolean result = p.print(zpl);//打印
        return result;
    }

    public static void main(String[] args) {
        ZplPrinter p = new ZplPrinter("ZDesigner GT800 (EPL)");
        p.printBarcode(p);

    }
}

代码解析:
首先要找到打印机:原博主是通过远程分享的方式\pch啥玩意的,我是直接根据打印机的名字来,具体的可以看下面这个方法的service.getName,自己debug找一下自己的打印机名字就知道了

        PrintService[] services = PrintServiceLookup.lookupPrintServices(null,null);
        if (services != null && services.length > 0) {
            for (PrintService service : services) {
                if (printerURI.equals(service.getName())) {
                    printService = service;
                    break;
                }
            }
        }

第二步就是那个lib文件,自己下了自己放
第三步就看如下这个方法里面的东西了,精髓都在这了:

    //^B3N,Y,Y  code39条形码
    public  boolean printBarcode(ZplPrinter p){
        //1.打印单个条码
        String bar0 = "D21066000101";//条码内容
        String str = "厦门湖里永康门诊部";
        String bar0Zpl = "^FO190,90^BY1.4,3,80^BCN,60,N,N,N^FD${data}^FS";//条码样式模板
        p.setBarcode(bar0, bar0Zpl);

        p.setCharR(bar0,200,60,25,25);
        content += "^CI26^SEE:GB18030.DAT^CWJ,E:MSUNG24^CI28^FO160,20^A1I,10,10^FD"+str+"^FS";
//        p.setText("厦门湖里永康门诊部", 160, 120, 10, 10, 30, 1, 0, 24);
        content += "^FO500,90^BY1.4,3,80^BCN,60,N,N,N^FD"+bar0+"^FS^FO510,60^A0I,25,25^FD"+bar0+"^FS^FT680,20^A1I,10,10^FD"+str+"^FS";
        String zpl = p.getZpl();
        System.out.println(zpl);
        boolean result = p.print(zpl);//打印
        return result;
    }

bar0Zpl 这个就是打印的模板,这个获取的方法,
第一,如果你的打印机比较高级,可以去下载ZebraDesigner 3 这个官网软件试试,会生成prn文件,我试过了我是用不了,不然就直接文本打开就可以看里面的zpl语言,这边这个链接可以看看你的打印机支持啥玩意:在文章的下面自己翻一下
第二:ZebraDesigner 3 for Developers 这个也是官方软件,这边可以去绑定变量然后去用,参考链接:工具的使用说明
第三:CODESOFT 2015这个软件要是有下过想研究的小伙伴感觉可以放弃了,这边中文什么的会乱码,有网上说找Unicode编码可以的,但是我没成功,有兴趣自己研究
第四:解答这个zpl:FO这个就是开始的意思,复制就好,后面两个190,90,是对应的xy坐标,自己去调整,BY这个是调整条形码的高度,宽度,然后中间那个空白的大小,那三个数字参数是这样的,第一个增幅是0.1,后面是1;BCN这个是D210000那个的字体调整,跟大小没啥关系,大小是下面方法调的

下面这个方法就是条形码替换,也可以直接写死,只是显得low一点

   public void setBarcode(String barcode,String zpl) {
        content += zpl.replace("${data}", barcode);
    }

再然后就是p.setCharR这个方法了,这个是我中间那一串数字的打印,里面有一个^AOI这个I是字体的方向,还有R,O好像,反正I是旋转180度,最下面我会附上这个zpl语言的文档,可以自己细看这个东西。
重点来了,中文字:我参考的是这篇博主的东西:但是这个里面的中文会乱码
所以我在中文这边里面加上了^CI28,这个就是转UTF-8的意思,这个博主里面有说到:具体可打开细看
^A1I,10,10 这个东西是调整中文的大小,我试过了,最小就是我图片那种的大小,负数也一样,只能往更大了调整,虽然我需要更小的字体,但是一直没法解决,如果有小伙伴研究出来了,可以滴滴我一下,不胜感激。中间那个数字字体可以xy坐标随便调整大小。
然后固定的^FS就是结尾的意思了
另一个重点同行打印两一个条码:^FD这个符号加上然后自己调整x坐标就可以了

这边附上几个觉得还不错zpl的语言文档:这个对字体的方向描述比较清晰
这个是整个zpl的文档,道客巴巴的比较规范
这个是其他博主写的,大同小异,得自己去看

基本上就是这些东西了,花了我三天时间,人都傻了,希望写了这么多,能对研究打印机的人有些帮助吧,要是有描述不太明白的地方或者有什么其他好的建议,可以给我留言或者直接邮箱我1095254145@qq.com
共勉!!

  • 19
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

情绪稳定的犟种

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值