Java 调用斑马打印机实现标签打印
最近的一个项目中,需要实现java调用斑马的打印机实现标签打印功能,百度了一些资源,找了不少人搞了一台快报废的斑马105SL 300DPI打印机,分分钟就搞出来了,不过要想调试成自己所需要的样式还是得花费一定的时间才能完成的。
以下是打印机来的效果:
代码实现
/**
* 采用点字字库 ts24.lib
* @create 2020-03-31 16:57
*/
@Slf4j
public class ZplPrinter {
private String printerURI = null; //打印机完整路径
private PrintService printService = null; //打印机服务
private byte[] font;
private String darkness = "~SD22"; //设置色带颜色的深度 0~30
private String width = "^PW1200"; //打印宽度 0~1500
private String begin = "^XA" + darkness + width; //标签格式以^XA开始
private String end = "^XZ";
private String content = ""; //打印内容
private String message = ""; //打印的结果信息
/**
* 构造方法
*/
public ZplPrinter(String printerURI){
this.printerURI = printerURI;
//加载字体
File file = new File("D://lib//ts24.lib");
if(file.exists()){
FileInputStream fis;
try{
fis = new FileInputStream(file);
font = new byte[fis.available()];
fis.read(font);
fis.close();
}catch(Exception e){
log.info(e.getMessage());
}
}else{
log.info("D://lib//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){
log.info("没有找到打印机:["+ printerURI +"]");
if(services != null && services.length > 0){
log.info("可用的打印机列表:");
for(PrintService service : services){
log.info("["+ service.getName() +"]");
}
}
}else{
log.info("找到打印机:["+ printerURI +"]");
log.info("打印机名称:["+ 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, int 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);
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) font[j + offset] & 0x00ff;
wcode = (int) font[j + offset + 1] & 0x00ff;
int qcode1 = (int) font[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 高度
* @param w 宽度
*/
public void setChar(String str, int x, int y, int h, int w) {
content += "^FO" + x + "," + y + "^A0," + h + "," + w + "^FD" + str + "^FS";
}
/**
* 重置ZPL指令,多张标签同时打印时需要调用
*/
public void resetZpl(){
begin = "^XA" + darkness + width;
end = "^XZ";
content = "";
}
/**
* 获取完整的ZPL指令
* @return
*/
public String getZpl(){
return begin + content + end;
}
/**
* 字符串转换为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;
}
/**
* 打印
* @param zpl 完整的ZPL
*/
public boolean print(String zpl){
if(printService==null){
log.info("打印出错:没有找到打印机["+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);
log.info("已打印");
return true;
} catch (PrintException e) {
log.info("打印出错:"+e.getMessage());
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
ZplPrinter printer = new ZplPrinter("Microsoft Print to PDF");
/**
* 文本
*/
printer.setChar("SN: 9Y203CCNW9A19396", 40, 20, 30, 30);
printer.setChar("MAC: 74EE2AEB1A52", 40, 70, 30, 30);
printer.setChar("DID: 9FCNY21EZJ460B190916", 40, 120, 30, 30);
printer.setChar("CMIIT: 2016DP9142", 40, 170, 30, 30);
// printer.setText("生产日期:2019", 40, 220 ,30, 30, 20, 1 , 1, 22);
// printer.setText("生产日期:", 40, 220, 56, 56, 30, 2, 2, 24);
// printer.setChar("2019", 120, 230, 40, 40);
//条码
// String data = "9Y203CCNW9A019396";//条码内容
// String dataZpl = "^FO260,250^BY2,11.0,10,40^BCC,80,N^FD${data}^FS";//条码样式模板
// printer.setBarcode(data, dataZpl);
//二维码
// String ewm = "9Y203CCNW9A019396";//条码内容
// String ewmZpl = "^FO430,50^BQ,2,6^CI26^FH^FDQA^FD${data}^FS";//条码样式模板
// printer.setBarcode(ewm, ewmZpl);
printer.resetZpl();
printer.setText("批号:", 20, 550, 56, 56, 30, 2, 2, 24);
printer.setChar("78787878788", 200, 560, 40, 40);
// printer.setText("批号:", 20, 220, 56, 56, 30, 1, 1, 24);
// printer.setChar("78787878788", 120, 230, 40, 40);
//下边的条码
String bar2 = "00000999990018822969";//20位
String bar2Paper = "^FO260,250^BY2,3.0,66^BCN,,Y,N,N^FD${data}^FS";//条码样式模板
printer.setBarcode(bar2,bar2Paper);
String zpl = printer.getZpl();
// System.out.println(zpl);
printer.print(zpl);
}
}
通过在网络上查找到的一些资源,实现起来难度也不是太大。
实现以上功能,需要一份点阵的字库文件,需要这份文件的可以给我留言。