• Android蓝牙打印机,带你真正了解各种打印格式 不及格的程序员


    Android蓝牙打印机,带你真正了解各种打印格式


     1.6 2016.10.20 10:54* 字数 1528 阅读 26478评论 126

    注意:本文原创,转载请注明出处。欢迎关注我的 简书 。

    本文主要讲解蓝牙打印机在打印小票的过程中,如何打印各种常见格式。由于之前需要调试打印格式,但是苦于网上没有详细的讲解教程,无奈只能自给自足,自己封装了一个。如果各位盆友正在或者曾经苦恼蓝牙打印机的打印格式,那么恭喜你,本篇博文就是你要寻找的。

    什么是蓝牙打印机

    是的,你没看错。一开始兔子哥先来介绍一下什么是蓝牙打印机。。。好吧,这个就交给百度了:

    蓝牙打印机(Bluetooth printer)就是将蓝牙技术应用在打印机上,摆脱打印机连线所带来的不便,实现无线打印,可以减少桌面上令人不快的电缆,并且可以将打印机远离主机任意搬动,摆放在房间中适合的位置。

    常见小票样式

     
    Paste_Image.png

    这个小票格式基本就是最常见的了。这里面的各种格式,都可以从蓝牙打印机的API里面找到。蓝牙打印机有好多API,我把常用的给封装了一下:PrintUtils.java

    /**
     * 复位打印机
     */
    public static final byte[] RESET = {0x1b, 0x40};
    
    /**
     * 左对齐
     */
    public static final byte[] ALIGN_LEFT = {0x1b, 0x61, 0x00};
    
    /**
     * 中间对齐
     */
    public static final byte[] ALIGN_CENTER = {0x1b, 0x61, 0x01};
    
    /**
     * 右对齐
     */
    public static final byte[] ALIGN_RIGHT = {0x1b, 0x61, 0x02};
    
    /**
     * 选择加粗模式
     */
    public static final byte[] BOLD = {0x1b, 0x45, 0x01};
    
    /**
     * 取消加粗模式
     */
    public static final byte[] BOLD_CANCEL = {0x1b, 0x45, 0x00};
    
    /**
     * 宽高加倍
     */
    public static final byte[] DOUBLE_HEIGHT_WIDTH = {0x1d, 0x21, 0x11};
    
    /**
     * 宽加倍
     */
    public static final byte[] DOUBLE_WIDTH = {0x1d, 0x21, 0x10};
    
    /**
     * 高加倍
     */
    public static final byte[] DOUBLE_HEIGHT = {0x1d, 0x21, 0x01};
    
    /**
     * 字体不放大
     */
    public static final byte[] NORMAL = {0x1d, 0x21, 0x00};
    
    /**
     * 设置默认行间距
     */
    public static final byte[] LINE_SPACING_DEFAULT = {0x1b, 0x32};
    

    打印实现

    打印小票,当然首先需要连接蓝牙打印机。至于如何扫描打印机,如何连接,这个都是标准的蓝牙方式,网上资料也很多。因为本博文主要关注打印格式,所以这个就不再赘述了。连接打印机后,需要从BluetoothSocket中获取OutputStream。然后接下来都是通过OutputStream来给打印机发送打印指令。

    • 设置打印格式
      设置打印格式,就要用到上面封装的那些指令了。
        /**
         * 设置打印格式
         *
         * @param command 格式指令
         */
        public static void selectCommand(byte[] command) {
            try {
                outputStream.write(command);
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    用法如下:

      PrintUtils.selectCommand(PrintUtils.RESET);
      PrintUtils.selectCommand(PrintUtils.LINE_SPACING_DEFAULT);
      PrintUtils.selectCommand(PrintUtils.ALIGN_CENTER);
      PrintUtils.selectCommand(PrintUtils.NORMAL);
    
    • 打印文字
        /**
         * 打印文字
         *
         * @param text 要打印的文字
         */
        public static void printText(String text) {
            try {
                byte[] data = text.getBytes("gbk");
                outputStream.write(data, 0, data.length);
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    用法如下:

      PrintUtils.printText("好吃的牛肉面" + "\n");
    

    打印文字的时候,最后都要手动拼接一个 "\n" 用来换行。

    完美吗?

    根据上面封装的代码,“貌似”是可以实现所有的打印样式了。是的,没毛病。因为上面既有打印格式的设置,又有打印文字的用法。打印小票是没问题了。but……

    这种格式如何实现?


     
    Paste_Image.png

    这种格式呢?


     
    Paste_Image.png

    有的盆友可能会说,这有啥问题的??? 并且给出了他们认为完美的解释:

      PrintUtils.printText("合计                           53.50" + "\n");
      PrintUtils.printText("抹零                            3.50" + "\n");
      PrintUtils.printText("项目            数量            金额" + "\n");
    

    可是,完美吗?
    你可能觉得人工加空格是可以“实现”需求。but……中间的空格,你知道应该添加多少吗?添加多了或者少了,打印出来的结果都会一塌糊涂!并且注意小票上都是要求对齐的!合计、抹零左侧对齐。金额右侧对齐。项目、数量、金额这三列都要中心对齐。。看到这里,这个人工加空格的做法,还完美吗?

    给我一个完美的解释!

    “海参炒面,海参呢?给我一个完美的解释!”
    “我叫海参,面是我炒的。完美不?”

    是的,我们需要一个完美的解释。到底如何实现上面说的打印两列打印三列的情况。
    首先,讲解之前,先设置几个默认值:

        /**
         * 打印纸一行最大的字节
         */
        private static final int LINE_BYTE_SIZE = 32;
    
        /**
         * 打印三列时,中间一列的中心线距离打印纸左侧的距离
         */
        private static final int LEFT_LENGTH = 16;
    
        /**
         * 打印三列时,中间一列的中心线距离打印纸右侧的距离
         */
        private static final int RIGHT_LENGTH = 16;
    
        /**
         * 打印三列时,第一列汉字最多显示几个文字
         */
        private static final int LEFT_TEXT_MAX_LENGTH = 5;
    

    我们知道,通用的打印纸都是有固定宽度的。经过大量测试,得出打印纸一行的最大字节数是32个字节。那么根据上面的注释,我们可以得到以下结论:

    LEFT_LENGTH + RIGHT_LENGTH = LINE_BYTE_SIZE
    

    这是毋庸置疑的。左侧宽度 + 右侧宽度 必须要等于打印纸总宽度。
    而且因为打印三列的时候,中间一列是要居中显示的,所以LEFT_LENGTHRIGHT_LENGTH都必须是总宽度32的一半,也就是必须是16.

    那么如何计算某个文字所占的字节数呢?

        /**
         * 获取数据长度
         *
         * @param msg
         * @return
         */
        @SuppressLint("NewApi")
        private static int getBytesLength(String msg) {
            return msg.getBytes(Charset.forName("GB2312")).length;
        }
    

    OK,准备了这么多,海参终于准备好了。接下来就可以准备炒面了~

    打印两列

        /**
         * 打印两列
         *
         * @param leftText  左侧文字
         * @param rightText 右侧文字
         * @return
         */
        @SuppressLint("NewApi")
        public static String printTwoData(String leftText, String rightText) {
            StringBuilder sb = new StringBuilder();
            int leftTextLength = getBytesLength(leftText);
            int rightTextLength = getBytesLength(rightText);
            sb.append(leftText);
    
            // 计算两侧文字中间的空格
            int marginBetweenMiddleAndRight = LINE_BYTE_SIZE - leftTextLength - rightTextLength;
    
            for (int i = 0; i < marginBetweenMiddleAndRight; i++) {
                sb.append(" ");
            }
            sb.append(rightText);
            return sb.toString();
        }
    

    那位说话了:“你这代码明明也是手动拼的空格啊,完美个毛啊!”。大兄弟你消消气,这里是通过逻辑进行拼接的空格,不是无脑的拼接。打印两列的步骤如下:

    • 拼接左侧一列的文字
    • 拼接两侧文字中间的空格
    • 拼接右侧一列的文字

    关键步骤是计算两侧文字中间的空格。怎么计算呢?很简单,总宽度 - 左侧文字长度 - 右侧文字长度 就是空格的长度。

    打印三列

        /**
         * 打印三列
         *
         * @param leftText   左侧文字
         * @param middleText 中间文字
         * @param rightText  右侧文字
         * @return
         */
        @SuppressLint("NewApi")
        public static String printThreeData(String leftText, String middleText, String rightText) {
            StringBuilder sb = new StringBuilder();
            // 左边最多显示 LEFT_TEXT_MAX_LENGTH 个汉字 + 两个点
            if (leftText.length() > LEFT_TEXT_MAX_LENGTH) {
                leftText = leftText.substring(0, LEFT_TEXT_MAX_LENGTH) + "..";
            }
            int leftTextLength = getBytesLength(leftText);
            int middleTextLength = getBytesLength(middleText);
            int rightTextLength = getBytesLength(rightText);
    
            sb.append(leftText);
            // 计算左侧文字和中间文字的空格长度
            int marginBetweenLeftAndMiddle = LEFT_LENGTH - leftTextLength - middleTextLength / 2;
    
            for (int i = 0; i < marginBetweenLeftAndMiddle; i++) {
                sb.append(" ");
            }
            sb.append(middleText);
    
            // 计算右侧文字和中间文字的空格长度
            int marginBetweenMiddleAndRight = RIGHT_LENGTH - middleTextLength / 2 - rightTextLength;
    
            for (int i = 0; i < marginBetweenMiddleAndRight; i++) {
                sb.append(" ");
            }
    
            // 打印的时候发现,最右边的文字总是偏右一个字符,所以需要删除一个空格
            sb.delete(sb.length() - 1, sb.length()).append(rightText);
            return sb.toString();
        }
    

    打印三列的步骤如下:

    • 拼接左侧一列的文字
    • 拼接左侧文字和中间文字中间的空格
    • 拼接中间的文字
    • 拼接右侧文字和中间文字中间的空格
    • 拼接右侧一列的文字

    在计算空格的时候,为了保证中间一列始终保持中心线对齐,所以在计算中间文字长度时候,都除以2。

    完整打印代码

    PrintUtils.selectCommand(PrintUtils.RESET);
    PrintUtils.selectCommand(PrintUtils.LINE_SPACING_DEFAULT);
    PrintUtils.selectCommand(PrintUtils.ALIGN_CENTER);
    PrintUtils.printText("美食餐厅\n\n");
    PrintUtils.selectCommand(PrintUtils.DOUBLE_HEIGHT_WIDTH);
    PrintUtils.printText("桌号:1号桌\n\n");
    PrintUtils.selectCommand(PrintUtils.NORMAL);
    PrintUtils.selectCommand(PrintUtils.ALIGN_LEFT);
    PrintUtils.printText(PrintUtils.printTwoData("订单编号", "201507161515\n"));
    PrintUtils.printText(PrintUtils.printTwoData("点菜时间", "2016-02-16 10:46\n"));
    PrintUtils.printText(PrintUtils.printTwoData("上菜时间", "2016-02-16 11:46\n"));
    PrintUtils.printText(PrintUtils.printTwoData("人数:2人", "收银员:张三\n"));
    
    PrintUtils.printText("--------------------------------\n");
    PrintUtils.selectCommand(PrintUtils.BOLD);
    PrintUtils.printText(PrintUtils.printThreeData("项目", "数量", "金额\n"));
    PrintUtils.printText("--------------------------------\n");
    PrintUtils.selectCommand(PrintUtils.BOLD_CANCEL);
    PrintUtils.printText(PrintUtils.printThreeData("面", "1", "0.00\n"));
    PrintUtils.printText(PrintUtils.printThreeData("米饭", "1", "6.00\n"));
    PrintUtils.printText(PrintUtils.printThreeData("铁板烧", "1", "26.00\n"));
    PrintUtils.printText(PrintUtils.printThreeData("一个测试", "1", "226.00\n"));
    PrintUtils.printText(PrintUtils.printThreeData("牛肉面啊啊", "1", "2226.00\n"));
    PrintUtils.printText(PrintUtils.printThreeData("牛肉面啊啊啊牛肉面啊啊啊", "888", "98886.00\n"));
    
    PrintUtils.printText("--------------------------------\n");
    PrintUtils.printText(PrintUtils.printTwoData("合计", "53.50\n"));
    PrintUtils.printText(PrintUtils.printTwoData("抹零", "3.50\n"));
    PrintUtils.printText("--------------------------------\n");
    PrintUtils.printText(PrintUtils.printTwoData("应收", "50.00\n"));
    PrintUtils.printText("--------------------------------\n");
    
    PrintUtils.selectCommand(PrintUtils.ALIGN_LEFT);
    PrintUtils.printText("备注:不要辣、不要香菜");
    PrintUtils.printText("\n\n\n\n\n");
    

    举一反三

     
    Paste_Image.png

    学习了上面的打印格式,那么这个小票怎么打印? 区别就是打印三列的时候,中间一列是偏右了。相信大家应该知道答案了。如果有疑问,可以给我留言。

    鉴于好多读者给我留言,要PrintUtils工具类代码,所以我把代码发布到github上了,大家可以自行下载。地址是:https://github.com/heroxuetao/PrintUtils

    如果有帮助到你,可以顺手来个star 。万分感谢!

    本文止


    打印二维码

    package com.sunmi.printerhelper.utils;
    
    import android.graphics.Bitmap;
    
    import java.io.ByteArrayOutputStream;
    
    //常用指令封装
    public class ESCUtil {
    
        public static final byte ESC = 0x1B;// Escape
        public static final byte FS =  0x1C;// Text delimiter
        public static final byte GS =  0x1D;// Group separator
        public static final byte DLE = 0x10;// data link escape
        public static final byte EOT = 0x04;// End of transmission
        public static final byte ENQ = 0x05;// Enquiry character
        public static final byte SP =  0x20;// Spaces
        public static final byte HT =  0x09;// Horizontal list
        public static final byte LF =  0x0A;//Print and wrap (horizontal orientation)
        public static final byte CR =  0x0D;// Home key
        public static final byte FF =  0x0C;// Carriage control (print and return to the standard mode (in page mode))
        public static final byte CAN = 0x18;// Canceled (cancel print data in page mode)
    
        //初始化打印机
        public static byte[] init_printer() {
            byte[] result = new byte[2];
            result[0] = ESC;
            result[1] = 0x40;
            return result;
        }
    
        //打印浓度指令
        public static byte[] setPrinterDarkness(int value){
            byte[] result = new byte[9];
            result[0] = GS;
            result[1] = 40;
            result[2] = 69;
            result[3] = 4;
            result[4] = 0;
            result[5] = 5;
            result[6] = 5;
            result[7] = (byte) (value >> 8);
            result[8] = (byte) value;
            return result;
        }
    
        /**
         * 打印单个二维码 sunmi自定义指令
         * @param code:            二维码数据
         * @param modulesize:    二维码块大小(单位:点, 取值 1 至 16 )
         * @param errorlevel:    二维码纠错等级(0 至 3)
         *                0 -- 纠错级别L ( 7%)
         *                1 -- 纠错级别M (15%)
         *                2 -- 纠错级别Q (25%)
         *                3 -- 纠错级别H (30%)
         */
        public static byte[] getPrintQRCode(String code, int modulesize, int errorlevel){
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            try{
                buffer.write(setQRCodeSize(modulesize));
                buffer.write(setQRCodeErrorLevel(errorlevel));
                buffer.write(getQCodeBytes(code));
                buffer.write(getBytesForPrintQRCode(true));
            }catch(Exception e){
                e.printStackTrace();
            }
            return buffer.toByteArray();
        }
    
        /**
         * 横向两个二维码 sunmi自定义指令
         * @param code1:            二维码数据
         * @param code2:            二维码数据
         * @param modulesize:    二维码块大小(单位:点, 取值 1 至 16 )
         * @param errorlevel:    二维码纠错等级(0 至 3)
         *                0 -- 纠错级别L ( 7%)
         *                1 -- 纠错级别M (15%)
         *                2 -- 纠错级别Q (25%)
         *                3 -- 纠错级别H (30%)
         */
        public static byte[] getPrintDoubleQRCode(String code1, String code2, int modulesize, int errorlevel){
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            try{
                buffer.write(setQRCodeSize(modulesize));
                buffer.write(setQRCodeErrorLevel(errorlevel));
                buffer.write(getQCodeBytes(code1));
                buffer.write(getBytesForPrintQRCode(false));
                buffer.write(getQCodeBytes(code2));
    
                //加入横向间隔
                buffer.write(new byte[]{0x1B, 0x5C, 0x18, 0x00});
    
                buffer.write(getBytesForPrintQRCode(true));
            }catch(Exception e){
                e.printStackTrace();
            }
            return buffer.toByteArray();
        }
    
        /**
         * 光栅打印二维码
         */
        public static byte[] getPrintQRCode2(String data, int size){
            byte[] bytes1  = new byte[4];
            bytes1[0] = GS;
            bytes1[1] = 0x76;
            bytes1[2] = 0x30;
            bytes1[3] = 0x00;
    
            byte[] bytes2 = BytesUtil.getZXingQRCode(data, size);
            return BytesUtil.byteMerger(bytes1, bytes2);
        }
    
        /**
         * 打印一维条形码
         */
        public static byte[] getPrintBarCode(String data, int symbology, int height, int width, int textposition){
            if(symbology < 0 || symbology > 10){
                return new byte[]{LF};
            }
    
            if(width < 2 || width > 6){
                width = 2;
            }
    
            if(textposition <0 || textposition > 3){
                textposition = 0;
            }
    
            if(height < 1 || height>255){
                height = 162;
            }
    
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            try{
                buffer.write(new byte[]{0x1D,0x66,0x01,0x1D,0x48,(byte)textposition,
                        0x1D,0x77,(byte)width,0x1D,0x68,(byte)height,0x0A});
    
                byte[] barcode;
                if(symbology == 10){
                    barcode = BytesUtil.getBytesFromDecString(data);
                }else{
                    barcode = data.getBytes("GB18030");
                }
    
    
                if(symbology > 7){
                    buffer.write(new byte[]{0x1D,0x6B,0x49,(byte)(barcode.length+2),0x7B, (byte) (0x41+symbology-8)});
                }else{
                    buffer.write(new byte[]{0x1D,0x6B,(byte)(symbology + 0x41),(byte)barcode.length});
                }
                buffer.write(barcode);
            }catch(Exception e){
                e.printStackTrace();
            }
            return buffer.toByteArray();
        }
    
        //光栅位图打印
        public static byte[] printBitmap(Bitmap bitmap){
            byte[] bytes1  = new byte[4];
            bytes1[0] = GS;
            bytes1[1] = 0x76;
            bytes1[2] = 0x30;
            bytes1[3] = 0x00;
    
            byte[] bytes2 = BytesUtil.getBytesFromBitMap(bitmap);
            return BytesUtil.byteMerger(bytes1, bytes2);
        }
    
        //光栅位图打印 设置mode
        public static byte[] printBitmap(Bitmap bitmap, int mode){
            byte[] bytes1  = new byte[4];
            bytes1[0] = GS;
            bytes1[1] = 0x76;
            bytes1[2] = 0x30;
            bytes1[3] = (byte) mode;
    
            byte[] bytes2 = BytesUtil.getBytesFromBitMap(bitmap);
            return BytesUtil.byteMerger(bytes1, bytes2);
        }
    
        //光栅位图打印
        public static byte[] printBitmap(byte[] bytes){
            byte[] bytes1  = new byte[4];
            bytes1[0] = GS;
            bytes1[1] = 0x76;
            bytes1[2] = 0x30;
            bytes1[3] = 0x00;
    
            return BytesUtil.byteMerger(bytes1, bytes);
        }
    
        /*
        *    选择位图指令 设置mode
        *    需要设置1B 33 00将行间距设为0
         */
        public static byte[] selectBitmap(Bitmap bitmap, int mode){
            return BytesUtil.byteMerger(BytesUtil.byteMerger(new byte[]{0x1B, 0x33, 0x00}, BytesUtil.getBytesFromBitMap(bitmap, mode)), new byte[]{0x0A, 0x1B, 0x32});
        }
    
        /**
         * 跳指定行数
         */
        public static byte[] nextLine(int lineNum) {
            byte[] result = new byte[lineNum];
            for (int i = 0; i < lineNum; i++) {
                result[i] = LF;
            }
    
            return result;
        }
    
        // ------------------------style set-----------------------------
        //设置默认行间距
        public static byte[] setDefaultLineSpace(){
            return new byte[]{0x1B, 0x32};
        }
    
        //设置行间距
        public static byte[] setLineSpace(int height){
            return new byte[]{0x1B, 0x33, (byte) height};
        }
    
        // ------------------------underline-----------------------------
        //设置下划线1点
        public static byte[] underlineWithOneDotWidthOn() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 45;
            result[2] = 1;
            return result;
        }
    
        //设置下划线2点
        public static byte[] underlineWithTwoDotWidthOn() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 45;
            result[2] = 2;
            return result;
        }
    
        //取消下划线
        public static byte[] underlineOff() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 45;
            result[2] = 0;
            return result;
        }
    
        // ------------------------bold-----------------------------
        /**
         * 字体加粗
         */
        public static byte[] boldOn() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 69;
            result[2] = 0xF;
            return result;
        }
    
        /**
         * 取消字体加粗
         */
        public static byte[] boldOff() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 69;
            result[2] = 0;
            return result;
        }
    
        // ------------------------character-----------------------------
        /*
        *单字节模式开启
         */
        public static byte[] singleByte(){
            byte[] result = new byte[2];
            result[0] = FS;
            result[1] = 0x2E;
            return result;
        }
    
        /*
        *单字节模式关闭
         */
        public static byte[] singleByteOff(){
            byte[] result = new byte[2];
            result[0] = FS;
            result[1] = 0x26;
            return result;
        }
    
        /**
         * 设置单字节字符集
         */
        public static byte[] setCodeSystemSingle(byte charset){
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 0x74;
            result[2] = charset;
            return result;
        }
    
        /**
         * 设置多字节字符集
         */
        public static byte[] setCodeSystem(byte charset){
            byte[] result = new byte[3];
            result[0] = FS;
            result[1] = 0x43;
            result[2] = charset;
            return result;
        }
    
        // ------------------------Align-----------------------------
    
        /**
         * 居左
         */
        public static byte[] alignLeft() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 97;
            result[2] = 0;
            return result;
        }
    
        /**
         * 居中对齐
         */
        public static byte[] alignCenter() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 97;
            result[2] = 1;
            return result;
        }
    
        /**
         * 居右
         */
        public static byte[] alignRight() {
            byte[] result = new byte[3];
            result[0] = ESC;
            result[1] = 97;
            result[2] = 2;
            return result;
        }
    
        //切刀
        public static byte[] cutter() {
            byte[] data = new byte[]{0x1d, 0x56, 0x01};
            return data;
        }
    
        //走纸到黑标
        public static byte[] gogogo(){
            byte[] data = new byte[]{0x1C, 0x28, 0x4C, 0x02, 0x00, 0x42, 0x31};
            return data;
        }
    
    
        ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////          private                /////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////
        private static byte[] setQRCodeSize(int modulesize){
            //二维码块大小设置指令
            byte[] dtmp = new byte[8];
            dtmp[0] = GS;
            dtmp[1] = 0x28;
            dtmp[2] = 0x6B;
            dtmp[3] = 0x03;
            dtmp[4] = 0x00;
            dtmp[5] = 0x31;
            dtmp[6] = 0x43;
            dtmp[7] = (byte)modulesize;
            return dtmp;
        }
    
        private static byte[] setQRCodeErrorLevel(int errorlevel){
            //二维码纠错等级设置指令
            byte[] dtmp = new byte[8];
            dtmp[0] = GS;
            dtmp[1] = 0x28;
            dtmp[2] = 0x6B;
            dtmp[3] = 0x03;
            dtmp[4] = 0x00;
            dtmp[5] = 0x31;
            dtmp[6] = 0x45;
            dtmp[7] = (byte)(48+errorlevel);
            return dtmp;
        }
    
    
        private static byte[] getBytesForPrintQRCode(boolean single){
            //打印已存入数据的二维码
            byte[] dtmp;
            if(single){        //同一行只打印一个QRCode, 后面加换行
                dtmp = new byte[9];
                dtmp[8] = 0x0A;
            }else{
                dtmp = new byte[8];
            }
            dtmp[0] = 0x1D;
            dtmp[1] = 0x28;
            dtmp[2] = 0x6B;
            dtmp[3] = 0x03;
            dtmp[4] = 0x00;
            dtmp[5] = 0x31;
            dtmp[6] = 0x51;
            dtmp[7] = 0x30;
            return dtmp;
        }
    
        private static byte[] getQCodeBytes(String code) {
            //二维码存入指令
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            try {
                byte[] d = code.getBytes("GB18030");
                int len = d.length + 3;
                if (len > 7092) len = 7092;
                buffer.write((byte) 0x1D);
                buffer.write((byte) 0x28);
                buffer.write((byte) 0x6B);
                buffer.write((byte) len);
                buffer.write((byte) (len >> 8));
                buffer.write((byte) 0x31);
                buffer.write((byte) 0x50);
                buffer.write((byte) 0x30);
                for (int i = 0; i < d.length && i < len; i++) {
                    buffer.write(d[i]);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return buffer.toByteArray();
        }
    }
  • 相关阅读:
    linux一些配置
    tomcat启动后,页面无法访问
    利用jmeter实现多IP压测
    java操作数据库
    excle中表头分割单元格
    常用的最大流算法 Dinic 和 最小费用最大流SPFA写法
    [kuangbin]带你飞之'网络流'专题
    (留坑以后再看)一般图'最大匹配' 带花树 算法
    二分图'多重匹配'
    二分图'最大匹配' HK 算法
  • 原文地址:https://www.cnblogs.com/ioriwellings/p/11506175.html
Copyright © 2020-2023  润新知