小票打印就是向打印设备发送控制打印格式的指令集,而这些打印格式需要去查询对应打印机的API文档,这里我把常用的api给封装了一下

  • 文字对齐方式
  • 打印字体大小
  • 字体是否加粗
  • 打印二维码
  • 打印条形码
  • 切纸
  • 打开钱箱
  • 字符串转字节数组
  • 字符拼接

PrintFormatUtils.java

/*** 打印格式* Created by john on 17-3-23.*/public class PrintFormatUtils {// 对齐方式public static final int ALIGN_LEFT = 0;     // 靠左public static final int ALIGN_CENTER = 1;   // 居中public static final int ALIGN_RIGHT = 2;    // 靠右//字体大小public static final int FONT_NORMAL = 0;    // 正常public static final int FONT_MIDDLE = 1;    // 中等public static final int FONT_BIG = 2;       // 大//加粗模式public static final int FONT_BOLD = 0;              // 字体加粗public static final int FONT_BOLD_CANCEL = 1;       // 取消加粗/*** 打印二维码* @param qrCode* @return*/public static String getQrCodeCmd(String qrCode) {byte[] data;int store_len = qrCode.length() + 3;byte store_pL = (byte) (store_len % 256);byte store_pH = (byte) (store_len / 256);// QR Code: Select the model//              Hex     1D      28      6B      04      00      31      41      n1(x32)     n2(x00) - size of model// set n1 [49 x31, model 1] [50 x32, model 2] [51 x33, micro qr code]// https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=140byte[] modelQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x04, (byte)0x00, (byte)0x31, (byte)0x41, (byte)0x32, (byte)0x00};// QR Code: Set the size of module// Hex      1D      28      6B      03      00      31      43      n// n depends on the printer// https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=141byte[] sizeQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x03, (byte)0x00, (byte)0x31, (byte)0x43, (byte)0x08};//          Hex     1D      28      6B      03      00      31      45      n// Set n for error correction [48 x30 -> 7%] [49 x31-> 15%] [50 x32 -> 25%] [51 x33 -> 30%]// https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=142byte[] errorQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x03, (byte)0x00, (byte)0x31, (byte)0x45, (byte)0x31};// QR Code: Store the data in the symbol storage area// Hex      1D      28      6B      pL      pH      31      50      30      d1...dk// https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=143//                        1D          28          6B         pL          pH  cn(49->x31) fn(80->x50) m(48->x30) d1…dkbyte[] storeQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, store_pL, store_pH, (byte)0x31, (byte)0x50, (byte)0x30};// QR Code: Print the symbol data in the symbol storage area// Hex      1D      28      6B      03      00      31      51      m// https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=144byte[] printQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x03, (byte)0x00, (byte)0x31, (byte)0x51, (byte)0x30};data = byteMerger(modelQR, sizeQR);data = byteMerger(data, errorQR);data = byteMerger(data, storeQR);data = byteMerger(data, qrCode.getBytes());data = byteMerger(data, printQR);return new String(data);}/*** 打印条码* @param barcode* @return*/public static String getBarcodeCmd(String barcode) {// 打印 Code-128 条码时需要使用字符集前缀// "{A" 表示大写字母// "{B" 表示所有字母,数字,符号// "{C" 表示数字,可以表示 00 - 99 的范围byte[] data;String btEncode;if (barcode.length() < 18) {// 字符长度小于15的时候直接输出字符串btEncode = "{B" + barcode;} else {// 否则做一点优化int startPos = 0;btEncode = "{B";for (int i = 0; i < barcode.length(); i++) {char curChar = barcode.charAt(i);if (curChar < 48 || curChar > 57 || i == (barcode.length() - 1)) {// 如果是非数字或者是最后一个字符if (i - startPos >= 10) {if (startPos == 0) {btEncode = "";}btEncode += "{C";boolean isFirst = true;int numCode = 0;for (int j = startPos; j < i; j++) {if (isFirst) { // 处理第一位numCode = (barcode.charAt(j) - 48) * 10;isFirst = false;} else { // 处理第二位numCode += (barcode.charAt(j) - 48);btEncode += (char) numCode;isFirst = true;}}btEncode += "{B";if (!isFirst) {startPos = i - 1;} else {startPos = i;}}for (int k = startPos; k <= i; k++) {btEncode += barcode.charAt(k);}startPos = i + 1;}}}// 设置 HRI 的位置,02 表示下方byte[] hriPosition = {(byte) 0x1d, (byte) 0x48, (byte) 0x02};// 最后一个参数表示宽度 取值范围 1-6 如果条码超长则无法打印byte[] width = {(byte) 0x1d, (byte) 0x77, (byte) 0x02};byte[] height = {(byte) 0x1d, (byte) 0x68, (byte) 0xfe};// 最后两个参数 73 : CODE 128 || 编码的长度byte[] barcodeType = {(byte) 0x1d, (byte) 0x6b, (byte) 73, (byte) btEncode.length()};byte[] print = {(byte) 10, (byte) 0};data = PrintFormatUtils.byteMerger(hriPosition, width);data = PrintFormatUtils.byteMerger(data, height);data = PrintFormatUtils.byteMerger(data, barcodeType);data = PrintFormatUtils.byteMerger(data, btEncode.getBytes());data = PrintFormatUtils.byteMerger(data, print);return new String(data);}/*** 切纸* @return*/public static String getCutPaperCmd() {// 走纸并切纸,最后一个参数控制走纸的长度byte[] data = {(byte) 0x1d, (byte) 0x56, (byte) 0x42, (byte) 0x15};return new String(data);}/*** 对齐方式* @param alignMode* @return*/public static String getAlignCmd(int alignMode) {byte[] data = {(byte) 0x1b, (byte) 0x61, (byte) 0x0};if (alignMode == ALIGN_LEFT) {data[2] = (byte) 0x00;} else if (alignMode == ALIGN_CENTER) {data[2] = (byte) 0x01;} else if (alignMode == ALIGN_RIGHT) {data[2] = (byte) 0x02;}return new String(data);}/*** 字体大小* @param fontSize* @return*/public static String getFontSizeCmd(int fontSize) {byte[] data = {(byte) 0x1d, (byte) 0x21, (byte) 0x0};if (fontSize == FONT_NORMAL) {data[2] = (byte) 0x00;} else if (fontSize == FONT_MIDDLE) {data[2] = (byte) 0x01;} else if (fontSize == FONT_BIG) {data[2] = (byte) 0x11;}return new String(data);}/*** 加粗模式* @param fontBold* @return*/public static String getFontBoldCmd(int fontBold) {byte[] data = {(byte) 0x1b, (byte) 0x45, (byte) 0x0};if (fontBold == FONT_BOLD) {data[2] = (byte) 0x01;} else if (fontBold == FONT_BOLD_CANCEL) {data[2] = (byte) 0x00;}return new String(data);}/*** 打开钱箱* @return*/public static String getOpenDrawerCmd() {byte[] data = new byte[4];data[0] = 0x10;data[1] = 0x14;data[2] = 0x00;data[3] = 0x00;return new String(data);}/*** 字符串转字节数组* @param str* @return*/public static byte[] stringToBytes(String str) {byte[] data = null;try {byte[] strBytes = str.getBytes("utf-8");data = (new String(strBytes, "utf-8")).getBytes("gbk");} catch (UnsupportedEncodingException exception) {exception.printStackTrace();}return data;}/*** 字节数组合并* @param bytesA* @param bytesB* @return*/public static byte[] byteMerger(byte[] bytesA, byte[] bytesB) {byte[] bytes = new byte[bytesA.length + bytesB.length];System.arraycopy(bytesA, 0, bytes, 0, bytesA.length);System.arraycopy(bytesB, 0, bytes, bytesA.length, bytesB.length);return bytes;}
}

有了打印格式,还要对具体的打印小票设置打印模板,主要就是利用上面的打印格式工具类,进行字符或字符串拼接,设置文字间空格的长度,以及使用换行符换行等。

有些小票打印的内容有可能是通用的,比如底部结束语–可能是公司宣传语或广告语,这些内容是否展示需要根据具体需求加以控制,还有二维码、条形码打印,是否切纸等需要根据实际场景取舍,所以最好封装一个打印配置类,以控制打印内容显示。

/*** 打印模板*/
public class PrintContract {/*** 打印内容*/public static StringBuilder createXxTxt(String ...) {StringBuilder builder = new StringBuilder();//设置大号字体以及加粗builder.append(PrintFormatUtils.getFontSizeCmd(PrintFormatUtils.FONT_BIG));builder.append(PrintFormatUtils.getFontBoldCmd(PrintFormatUtils.FONT_BOLD));// 标题builder.append("Title");//换行,调用次数根据换行数来控制addLineSeparator(builder);//设置普通字体大小、不加粗builder.append(PrintFormatUtils.getFontSizeCmd(PrintFormatUtils.FONT_NORMAL));builder.append(PrintFormatUtils.getFontBoldCmd(PrintFormatUtils.FONT_BOLD_CANCEL));//内容......//设置某两列文字间空格数, x需要计算出来addIdenticalStrToStringBuilder(builder, x, " ");//切纸builder.append(PrintFormatUtils.getCutPaperCmd());return builder;}/*** 向StringBuilder中添加指定数量的相同字符** @param printCount   添加的字符数量* @param identicalStr 添加的字符*/private static void addIdenticalStrToStringBuilder(StringBuilder builder, int printCount, String identicalStr) {for (int i = 0; i < printCount; i++) {builder.append(identicalStr);}}/*** 根据字符串截取前指定字节数,按照GBK编码进行截取** @param str 原字符串* @param len 截取的字节数* @return 截取后的字符串*/private static String subStringByGBK(String str, int len) {String result = null;if (str != null) {try {byte[] a = str.getBytes("GBK");if (a.length <= len) {result = str;} else if (len > 0) {result = new String(a, 0, len, "GBK");int length = result.length();if (str.charAt(length - 1) != result.charAt(length - 1)) {if (length < 2) {result = null;} else {result = result.substring(0, length - 1);}}}} catch (Exception e) {e.printStackTrace();}}return result;}/*** 添加换行符*/private static void addLineSeparator(StringBuilder builder) {builder.append("\n");}/*** 在GBK编码下,获取其字符串占据的字符个数*/private static int getCharCountByGBKEncoding(String text) {try {return text.getBytes("GBK").length;} catch (Exception e) {e.printStackTrace();return 0;}}/*** 打印相关配置*/public static class PrintConfig {public int maxLength = 30;public boolean printBarcode = false;  // 打印条码public boolean printQrCode = false;   // 打印二维码public boolean printEndText = true;   // 打印结束语public boolean needCutPaper = false;  // 是否切纸}}

有了打印模板,接下来就是调用打印设备打印方法发送打印指令

//调用打印机打印方法,传入上面某个小票打印模板返回的字符串
String str = PrintContract.createXxTxt(...);
printer.print(str, null);//打开钱箱方法
printer.print(PrintFormatUtils.getOpenDrawerCmd(), null);

Android打印机--小票打印格式及模板设置相关推荐

  1. pyqt5 listview 不默认选中_pyqt5 商店小票打印的实现模板

    说明 最近在用pyqt5做商店小票打印,用的是得力DL-581PW(NEW)热敏小票打印机. 商店小票打印,属于escpos打印. 在网上找了很多实现方法,看了很多相关文章,经历了很多困难,最后终于实 ...

  2. pyqt5 商店小票打印的实现模板

    说明 最近在用pyqt5做商店小票打印,用的是得力DL-581PW(NEW)热敏小票打印机. 商店小票打印,属于escpos打印. 在网上找了很多实现方法,看了很多相关文章,经历了很多困难,最后终于实 ...

  3. python打印小票_pyqt5 商店小票打印的实现模板

    说明 最近在用pyqt5做商店小票打印,用的是得力DL-581PW(NEW)热敏小票打印机. 商店小票打印,属于escpos打印. 在网上找了很多实现方法,看了很多相关文章,经历了很多困难,最后终于实 ...

  4. 打印机可以打印不能扫描怎么弄_打印机可以打印不能扫描怎么设置

    其他回答 有.如果要打照片级(专用照片纸),最好别用太便宜的(主要是墨盒太贵). 喷墨打黑白,很亏的. 广告公司,建议买个好点的喷墨机,同时让卖的人给你加装外部供墨,那就什么都... 激光的一般只能打 ...

  5. Android打印机--蓝牙打印

    关于Android蓝牙打印和网络打印,其实都是利用Socket通信机制,只是蓝牙打印将socket做了一层封装BluetoothSocket ,打印的数据都是以流的方式进行传输或保存的,程序需要数据的 ...

  6. pos机顾显java控制打印内容_Delphi下POS机控制钱箱,客显,打印机,小票打印

    1.控制POS机的客户显示屏 procedure TFrmMain.ShowMoney(Money_Port:   String;Money_String:String); //Moneey_Port ...

  7. Delphi下POS机控制钱箱,客显,打印机,小票打印

    1.控制POS机的客户显示屏 procedure TFrmMain.ShowMoney(Money_Port:   String;Money_String:String); //Moneey_Port ...

  8. Android打印机--TSC 标签打印

    打印机按照连接方式分为USB打印机.蓝牙打印机.网络打印机.云打印机.内联打印机:按照打印纸张大小分为带切刀的80厨房打印机和58热敏票据打印机:按照打印结果分为小票打印机和标签打印机:关于小票打印, ...

  9. 蓝牙打印 设置打印样式_Android蓝牙打印机,带你真正了解各种打印格式

    注意:本文原创,转载请注明出处.欢迎关注我的 简书 . 本文主要讲解蓝牙打印机在打印小票的过程中,如何打印各种常见格式.由于之前需要调试打印格式,但是苦于网上没有详细的讲解教程,无奈只能自给自足,自己 ...

最新文章

  1. 在WebStorm里面搜索文件中出现的中文字符
  2. 安卓系统底层C语言算法之测试参数是几个long型的算法
  3. MTK深圳公司嵌入式软件工程师笔试题(含部分答案)
  4. python怎么导入文本-Python 导入文件问题
  5. c++状态模式state
  6. 【语义分割】OCRNet:Object-Context Representations for Semantic Segmentation
  7. SpringCloud面试题分享
  8. springboot之rabbitmq
  9. 面向对象——类设计(二)
  10. Android 集成科大讯飞语音并实现语音识别
  11. 基于SSM+Bootstrap+MYSQL演唱会网上订票系统
  12. ssm项目实战------------OA管理项目
  13. Axial Attention 和 Criss-Cross Attention及其代码实现
  14. 荆门市建设企业网站多少钱,荆门口碑好的网站建设多少钱
  15. 研发流程——变更流程管控
  16. 使用selenium获取网页源码
  17. [翻译]X窗口管理器的原理剖析(一)
  18. ps网页效果图转html,Photoshop制作简洁干净的网页效果图
  19. 天使的微笑——《天使爱美丽》
  20. 解决高度塌陷的几种方法

热门文章

  1. 批处理文件删除注册表数据
  2. Mac系统给移动硬盘分区(图文)
  3. 基础知识 | BOM 事件
  4. 优思学院:如何注册六西格玛黑带?
  5. 数据分析进阶 - 使用Pyecharts搭建数据看板
  6. 基于ThinkPHP框架的简单的后台管理系统
  7. Contest2656 - 2021ACM俱乐部后备营个人训练赛第4场
  8. Composer 使用简单教程
  9. Hadoop分布式高可用HA集群搭建笔记(含Hive之构建),java高级架构师视频
  10. 中国医科大学计算机本科在线作业,16春中国医科大学《计算机应用基础(本科)》在线作业答案...