Java直接控制打印机打印

我们是一家专业做酒店餐饮软件的公司,餐饮软件一个重要的功能就是后厨打印问题,前台点菜完毕,后厨立刻打印出单子,这样就减少人工递单的麻烦,节省时间,提高翻台率。这种信息化解决方案对打印技术要求很高,理论上最好 100% 不丢单,也就是每次点菜后厨都会相应出单子,但是实际上行不通,为什么呢?因为网线、打印机、网卡等都有可能有问题,别说打印机等硬件因为厨房油烟问题损坏,我们甚至碰到过网线被老鼠咬断的情况,总之硬件网络故障防不胜防,所以只能退而求其次,就是有问题不可怕,程序能够判断是否出了问题,并能给出提示,便于服务员处理,及时补单。

   如果我们用安装 Windows 驱动的方法来实现后厨打印,那么肯定是不行的,因为我们只能单向向驱动程序抛包,不能从驱动程序获得任何返回值,没有办法了解是否打印成功,而且经过验证后发现,热敏打印机驱动打印时速度上非常慢。而且更为严重的是,有时候因为后厨打印机过多,Windows 驱动甚至会因为网络堵塞自作主张将包丢弃,没有任何提示。这在行业应用中是不行的,会给用户带来损失,所以想到了绕过 Windows 驱动,直接写端口的方法。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.common.util.portprinter;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.OutputStream;  
  5.   
  6. import com.common.util.PrinterParameterConf;  
  7.   
  8. /** 
  9.  * @author ChenMing 
  10.  * 
  11.  */  
  12. public class PortPrinterBase {  
  13.     private OutputStream out;  
  14.     protected int lineCount = 40;  
  15.     private String printType="0";  
  16.     public PortPrinterBase(OutputStream out, String printType){  
  17.         this.out = out;  
  18.         this.printType = printType;  
  19.         initPrinter();  
  20.         String lineCountStr = PrinterParameterConf.printerParameterConf.getProperty(PrinterParameterConf.LINEPRINTERCHARCOUNT_NAME);  
  21.         try{  
  22.             int temp = Integer.parseInt(lineCountStr);  
  23.             this.lineCount = temp;  
  24.         }catch(Exception e){      
  25.         }  
  26.     }  
  27.     protected final String LEFT = "LEFT";  
  28.     protected final String CENTER = "CENTER";  
  29.     protected final String RIGHT = "RIGHT";  
  30.     public static final byte HT = 0x9;  
  31.     public static final byte LF = 0x0A;  
  32.     public static final byte CR = 0x0D;  
  33.     public static final byte ESC = 0x1B;  
  34.     public static final byte DLE = 0x10;  
  35.     public static final byte GS = 0x1D;  
  36.     public static final byte FS = 0x1C;  
  37.     public static final byte STX = 0x02;  
  38.     public static final byte US = 0x1F;  
  39.     public static final byte CAN = 0x18;  
  40.     public static final byte CLR = 0x0C;  
  41.     public static final byte EOT = 0x04;  
  42.       
  43.     /* 初始化打印机 */   
  44.     public static final byte[] ESC_INIT = new byte[] {ESC, '@'};  
  45.     /* 设置标准模式 */  
  46.     public static final byte[] ESC_STANDARD = new byte[] {ESC, 'S'};  
  47.     /* 设置汉字打印模式 */  
  48.     public static final byte[] ESC_CN_FONT = new byte[] {FS, '&'};  
  49.     /* 选择字符集 */  
  50.     public static final byte[] ESC_SELECT_CHARACTER = new byte[] {ESC, 'R'9};  
  51.     /* 设置用户自定义汉字字体 焗7118 */  
  52.     public static final byte[] ESC_FS_2 = new byte[] {FS, 0x320x710x18};  
  53.     /* 取消用户自定义字体 */  
  54.     public static final byte[] ESC_CANCEL_DEFINE_FONT = new byte[]{ESC, '%'0};  
  55.     /* 打开钱箱指令 */   
  56.     public static final byte[] ESC_OPEN_DRAWER = new byte[]{ESC, 'p'0x000x10, (byte0xff};  
  57.     /* 切纸指令GS V m    
  58.     * m  0,48 Executes a full cut(cuts the paper completely) 
  59.     *    1,49 Excutes a partilal cut(one point left uncut) 
  60.     */   
  61.    public static final byte[] POS_CUT_MODE_FULL = new byte[]{GS, 'V'0x00};  
  62.    public static final byte[] POS_CUT_MODE_PARTIAL = new byte[]{GS, 'V'0x01};  
  63.     /* 西文字符 (半宽)字体A (6 ×12),汉字字符 (全宽)字体A (12×12) */   
  64.     public static final byte[] ESC_FONT_A = new byte[]{ESC, '!'0};  
  65.     /* 西文字符 (半宽)字体B (8×16),汉字字符 (全宽)字体B (16×16) */   
  66.     public static final byte[] ESC_FONT_B = new byte[]{ESC, '!'1};  
  67.     /* 12*24   0/48*/  
  68.     public static final byte[] ESC_FONTA= new byte[]{ESC, 'M'48};  
  69.     /* 9*17    1/49*/  
  70.     public static final byte[] ESC_FONTB= new byte[]{ESC, 'M'1};  
  71.     /* 默认颜色字体指令 */   
  72.     public static final byte[] ESC_FONT_COLOR_DEFAULT = new byte[] {ESC, 'r'0x00};  
  73.     /* 红色字体指令 */   
  74.     public static final byte[] ESC_FONT_COLOR_RED = new byte[] {ESC, 'r'0x01 };  
  75.     /* 标准大小 */   
  76.     public static final byte[] FS_FONT_ALIGN = new byte[]{FS, 0x211, ESC, 0x211};   
  77.     /* 横向放大一倍 */   
  78.     public static final byte[] FS_FONT_ALIGN_DOUBLE = new byte[]{FS, 0x214, ESC, 0x214};   
  79.     /* 纵向放大一倍 */   
  80.     public static final byte[] FS_FONT_VERTICAL_DOUBLE = new byte[]{FS, 0x218, ESC, 0x218, GS, '!'0x01};   
  81.     /* 横向纵向都放大一倍 */   
  82.     public static final byte[] FS_FONT_DOUBLE = new byte[]{FS, 0x2112, ESC, 0x2148};   
  83.     /* 靠左打印命令 */   
  84.     public static final byte[] ESC_ALIGN_LEFT = new byte[]{0x1b,'a'0x00};  
  85.     /* 居中打印命令 */   
  86.     public static final byte[] ESC_ALIGN_CENTER = new byte[]{0x1b,'a'0x01};  
  87.     /* 靠右打印命令 */   
  88.     public static final byte[] ESC_ALIGN_RIGHT = new byte[]{0x1b,'a'0x02};  
  89.     /* 字体加粗 */  
  90.     public static final byte[] ESC_SETTING_BOLD = new byte[]{ESC, 0x451};  
  91.     /* 取消字体加粗 */  
  92.     public static final byte[] ESC_CANCEL_BOLD = new byte[]{ESC, 0x450};  
  93.     //DLE EOT n 实时状态传送  
  94.     //如果返回结果为22  
  95.     /** 
  96.      * 、DLE EOT n 实时状态传送 
  97.         [格式] ASCII码 DLE EOT n 
  98.         十六进制码 10 04 n 
  99.         十进制码 16 4 n 
  100.         [范围] 1 ≤ n ≤ 4 
  101.         [描述] 根据下列参数,实时传送打印机状态,参数 n 用来指定所要传送的打印机状态: 
  102.         n = 1:传送打印机状态 
  103.         n = 2:传送脱机状态 
  104.         n = 3:传送错误状态 
  105.         n = 4:传送纸传感器状态 
  106.         [注释] 打印机收到该命令后立即返回相关状态 
  107.         该命令尽量不要插在2个或更多字节的命令序列中。 
  108.         即使打印机被ESC =(选择外设)命令设置为禁止,该命令依然有效。 
  109.         打印机传送当前状态,每一状态用1个字节数据表示。 
  110.         打印机传送状态时并不确认主机是否收到。 
  111.         打印机收到该命令立即执行。 
  112.         该命令只对串口打印机有效。打印机在任何状态下收到该命令都立即执行。 
  113.      */  
  114.     public static final byte[] PRINT_STATE_DLE_EOT = new byte[] {DLE, EOT,0x01};  
  115.       
  116.     public void initPrinter(){  
  117.         try {  
  118.             //modify by gongqiyi 20090917   
  119.             //ESC_INIT 将在清空缓存区的数据  
  120.             //out.write(ESC_INIT);  
  121.             //自定义字体  
  122.             //out.write(ESC_FS_2);  
  123.             out.write(ESC_STANDARD);  
  124.             out.write(ESC_CANCEL_DEFINE_FONT);  
  125.             out.write(ESC_FONTA);  
  126.             out.write(ESC_SELECT_CHARACTER);  
  127.             //进入汉字模式打印  
  128.             //out.write(ESC_CN_FONT);  
  129.               
  130.               
  131.             //out.write(ESC_FONT_B);  
  132.             //out.write(ESC_FONTA);  
  133.         } catch (IOException e) {  
  134.             e.printStackTrace();  
  135.         }  
  136.     }  
  137.     /** 
  138.      * 走纸到切纸位置并切纸 
  139.      */  
  140.     public void executeLineFeedAndPaperCut(){  
  141.         try {  
  142.             out.write(PrinterParameterConf.printerParameterConf.getProperty  
  143.           (PrinterParameterConf.PRINTCUTLINE_NAME).getBytes());  
  144.             out.write(POS_CUT_MODE_PARTIAL);  
  145.         } catch (IOException e) {  
  146.             e.printStackTrace();  
  147.         }  
  148.     }  
  149.     /** 
  150.      * 单据头打印 
  151.      * @param str 
  152.      */  
  153.     public void billHeaderPrinter(String str){  
  154.         try {  
  155.             out.write(ESC_ALIGN_CENTER);  
  156.             out.write(FS_FONT_DOUBLE);  
  157.             out.write((str+"\n").getBytes());  
  158.             out.write(LF);  
  159.         } catch (IOException e) {  
  160.             e.printStackTrace();  
  161.         }  
  162.     }  
  163.     /** 
  164.      * 叫单号打印 
  165.      * @param str 
  166.      */  
  167.     public void callNumPrinter(String str){  
  168.         try {  
  169.             out.write(ESC_ALIGN_LEFT);  
  170.             out.write(FS_FONT_DOUBLE);  
  171.             out.write((str+"\n").getBytes());  
  172.         } catch (IOException e) {  
  173.             e.printStackTrace();  
  174.         }  
  175.     }  
  176.     /** 
  177.      * 双倍大小字体 
  178.      * @param str 
  179.      */  
  180.     public void doubleSizePrinter(String str, String align){  
  181.         try {  
  182.             if(CENTER.equals(align)){  
  183.                 out.write(ESC_ALIGN_LEFT);  
  184.             }else if(RIGHT.equals(align)){  
  185.                 out.write(ESC_ALIGN_RIGHT);  
  186.             }else{  
  187.                 out.write(ESC_ALIGN_LEFT);  
  188.             }  
  189.             out.write(FS_FONT_DOUBLE);  
  190.             out.write((str+"\n").getBytes());  
  191.             //out.write(LF);  
  192.         } catch (IOException e) {  
  193.             e.printStackTrace();  
  194.         }  
  195.     }  
  196.     /** 
  197.      * 标准字体打印一行 
  198.      * @param str 需打印的字符串 
  199.      * @param align 打印的位置 LEFT/CENTER/RIGHT 其他为默认居左打印 
  200.      */  
  201.     public void standardPrinterLine(String str, String align){  
  202.         try{  
  203.             if(CENTER.equals(align)){  
  204.                 out.write(ESC_ALIGN_CENTER);  
  205.                 out.write(FS_FONT_ALIGN);  
  206.                 out.write(ESC_CN_FONT);  
  207.                 out.write(ESC_CANCEL_BOLD);  
  208.                 if("1".equals(printType)){  
  209.                     out.write(ESC_FONTA);  
  210.                 }else{  
  211.                     out.write(ESC_FONT_B);  
  212.                 }  
  213.                 out.write(str.getBytes());  
  214.             }else if(RIGHT.equals(align)){  
  215.                 out.write(ESC_ALIGN_RIGHT);  
  216.                 out.write(FS_FONT_ALIGN);  
  217.                 out.write(ESC_CN_FONT);  
  218.                 out.write(ESC_CANCEL_BOLD);  
  219.                 if("1".equals(printType)){  
  220.                     out.write(ESC_FONTA);  
  221.                 }else{  
  222.                     out.write(ESC_FONT_B);  
  223.                 }  
  224.                 out.write(str.getBytes());  
  225.             }else{  
  226.                 out.write(ESC_ALIGN_LEFT);  
  227.                 out.write(FS_FONT_ALIGN);  
  228.                 out.write(ESC_CN_FONT);  
  229.                 out.write(ESC_CANCEL_BOLD);  
  230.                 if("1".equals(printType)){  
  231.                     out.write(ESC_FONTA);  
  232.                 }else{  
  233.                     out.write(ESC_FONT_B);  
  234.                 }  
  235.                 out.write(str.getBytes());  
  236.             }  
  237.             out.write("\n".getBytes());  
  238.         }catch(IOException e) {  
  239.             e.printStackTrace();  
  240.         }  
  241.     }  
  242.   
  243.     /** 
  244.      * 标准粗体字体打印一行 
  245.      * @param str 需打印的字符串 
  246.      * @param align 打印的位置 LEFT/CENTER/RIGHT 其他为默认居左打印 
  247.      */  
  248.     public void standardBoldPrinterLine(String str, String align){  
  249.         try{  
  250.             if(CENTER.equals(align)){  
  251.                 out.write(ESC_ALIGN_CENTER);  
  252.                 out.write(FS_FONT_ALIGN);  
  253.                 out.write(ESC_CN_FONT);  
  254.                 out.write(ESC_SETTING_BOLD);  
  255.                 if("1".equals(printType)){  
  256.                     out.write(ESC_FONTA);  
  257.                 }else{  
  258.                     out.write(ESC_FONT_B);  
  259.                 }  
  260.                 out.write(str.getBytes());  
  261.             }else if(RIGHT.equals(align)){  
  262.                 out.write(ESC_ALIGN_RIGHT);  
  263.                 out.write(FS_FONT_ALIGN);  
  264.                 out.write(ESC_CN_FONT);  
  265.                 out.write(ESC_SETTING_BOLD);  
  266.                 if("1".equals(printType)){  
  267.                     out.write(ESC_FONTA);  
  268.                 }else{  
  269.                     out.write(ESC_FONT_B);  
  270.                 }  
  271.                 out.write(str.getBytes());  
  272.             }else{  
  273.                 out.write(ESC_ALIGN_LEFT);  
  274.                 out.write(FS_FONT_ALIGN);  
  275.                 out.write(ESC_CN_FONT);  
  276.                 out.write(ESC_SETTING_BOLD);  
  277.                 if("1".equals(printType)){  
  278.                     out.write(ESC_FONTA);  
  279.                 }else{  
  280.                     out.write(ESC_FONT_B);  
  281.                 }  
  282.                 out.write(str.getBytes());  
  283.             }  
  284.             out.write("\n".getBytes());  
  285.         }catch(IOException e) {  
  286.             e.printStackTrace();  
  287.         }  
  288.     }  
  289.   
  290.     /** 
  291.      * 双倍宽字体按行打印 
  292.      * @param str 
  293.      * @param align 
  294.      */  
  295.     public void largeSizePrinterLine(String str, String align){  
  296.         try{  
  297.             if(CENTER.equals(align)){  
  298.                 out.write(ESC_ALIGN_CENTER);  
  299.                 out.write(FS_FONT_ALIGN_DOUBLE);  
  300.                 out.write(str.getBytes());  
  301.             }else if(RIGHT.equals(align)){  
  302.                 out.write(ESC_ALIGN_RIGHT);  
  303.                 out.write(FS_FONT_ALIGN_DOUBLE);  
  304.                 out.write(str.getBytes());  
  305.             }else{  
  306.                 out.write(ESC_ALIGN_LEFT);  
  307.                 out.write(FS_FONT_ALIGN_DOUBLE);  
  308.                 out.write(str.getBytes());  
  309.             }  
  310.             out.write("\n".getBytes());  
  311.         }catch(IOException e) {  
  312.             e.printStackTrace();  
  313.         }  
  314.     }  
  315.       
  316.     /** 
  317.      * 双倍高字体按行打印 
  318.      * @param str 
  319.      * @param align 
  320.      */  
  321.     public void largeHSizePrinterLine(String str, String align){  
  322.         try{  
  323.             if(CENTER.equals(align)){  
  324.                 out.write(ESC_ALIGN_CENTER);  
  325.                 out.write(FS_FONT_VERTICAL_DOUBLE);  
  326.                 out.write(str.getBytes());  
  327.             }else if(RIGHT.equals(align)){  
  328.                 out.write(ESC_ALIGN_RIGHT);  
  329.                 out.write(FS_FONT_VERTICAL_DOUBLE);  
  330.                 out.write(str.getBytes());  
  331.             }else{  
  332.                 out.write(ESC_ALIGN_LEFT);  
  333.                 out.write(FS_FONT_VERTICAL_DOUBLE);  
  334.                 out.write(str.getBytes());  
  335.             }  
  336.             out.write("\n".getBytes());  
  337.         }catch(IOException e) {  
  338.             e.printStackTrace();  
  339.         }  
  340.     }    /** 
  341.      * 大号字体红色按行打印 
  342.      * @param str 
  343.      * @param align 
  344.      */  
  345.     public void largeSizeRedPrinterLine(String str, String align){  
  346.         try{  
  347.             if(CENTER.equals(align)){  
  348.                 out.write(ESC_ALIGN_CENTER);  
  349.                 out.write(FS_FONT_ALIGN_DOUBLE);  
  350.                 out.write(ESC_FONT_COLOR_RED);  
  351.                 out.write(str.getBytes());  
  352.             }else if(RIGHT.equals(align)){  
  353.                 out.write(ESC_ALIGN_RIGHT);  
  354.                 out.write(FS_FONT_ALIGN_DOUBLE);  
  355.                 out.write(ESC_FONT_COLOR_RED);  
  356.                 out.write(str.getBytes());  
  357.             }else{  
  358.                 out.write(ESC_ALIGN_LEFT);  
  359.                 out.write(FS_FONT_ALIGN_DOUBLE);  
  360.                 out.write(ESC_FONT_COLOR_RED);  
  361.                 out.write(str.getBytes());  
  362.             }  
  363.             out.write("\n".getBytes());  
  364.         }catch(IOException e) {  
  365.             e.printStackTrace();  
  366.         }  
  367.     }  
  368.     public void openDrawer(){  
  369.         try {  
  370.             out.write(ESC_OPEN_DRAWER);  
  371.         } catch (IOException e) {  
  372.             e.printStackTrace();  
  373.         }  
  374.     }  
  375.     public String makePrintString(int lineChars, String txt1, String txt2){  
  376.         if(txt1 == null){  
  377.             txt1 = "";  
  378.         }  
  379.         if(txt2 == null){  
  380.             txt2 = "";  
  381.         }  
  382.         int spaces = 0;  
  383.         String tab = "";  
  384.         try{  
  385.             spaces = lineChars - (txt1.getBytes().length + txt2.getBytes().length);  
  386.             for (int j = 0 ; j < spaces ; j++){  
  387.                 tab += " ";  
  388.             }  
  389.         }catch(Exception e){  
  390.             e.printStackTrace();  
  391.         }  
  392.         return txt1 + tab + txt2;  
  393.     }  
  394.     public String makePrintString(int lineChars, String txt1, String txt2, String txt3){  
  395.         if(txt1 == null){  
  396.             txt1 = "";  
  397.         }  
  398.         if(txt2 == null){  
  399.             txt2 = "";  
  400.         }  
  401.         if(txt3 == null){  
  402.             txt3 = "";  
  403.         }  
  404.         int spaces = 0;  
  405.         int lineChars1 = lineChars*2/3;  
  406.         String tab = "";  
  407.         String returnStr = txt1;  
  408.         try{  
  409.             spaces = lineChars1 - (returnStr.getBytes().length + txt2.getBytes().length);  
  410.             for (int j = 0 ; j < spaces ; j++){  
  411.                 tab += " ";  
  412.             }  
  413.             returnStr = txt1 + tab + txt2;  
  414.             spaces = lineChars - (returnStr.getBytes().length + txt3.getBytes().length);  
  415.             tab = "";  
  416.             for (int j = 0 ; j < spaces ; j++){  
  417.                 tab += " ";  
  418.             }  
  419.             returnStr = returnStr + tab + txt3;  
  420.         }catch(Exception e){  
  421.             e.printStackTrace();  
  422.         }  
  423.         return returnStr;  
  424.     }  
  425. }  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值