Java 通过 Socket 实现小票打印

2/22/2017来源:ASP.NET技巧人气:1563

描述

 最近在研究java连接打印的方法,无脑百度了一番,发现有很多都是这样的模式。

根据java.awt中提供的一些打印的API,要实现打印,首先要获得打印对象,然后继承PRintable实现接口方法print,以便打印机进行打印,最后用用Graphics2D直接输出直接输出。 — CSDN @戴新美

  对于这样的方式,不是太懂,有的代码运行起来,会弹出一个面板选择任务,着实不便。但是无意间看到了一个 Android 的实现方式,让我眼前一亮,这不就是我想要的 ‘滑板鞋’ 么,哈哈,运行起来,打印机立马就有了反应。给我打开了另一扇门。立马记录下来权当是笔记吧,也可以给大家另一种思路。

源码

package com.example.printertest; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @ POS小票打印机 网口无驱打印 * *调用方法 new PrintLine().print(list,map,string); * @author Btboy1978 QQ: 138027869 * */ public class PrintLine { static String PRINT_ip = "192.168.1.254"; static int PRINT_PORT = 9100; Socket socket = null; OutputStream socketOut = null; OutputStreamWriter writer = null; String[] Colum_Name = new String[] { "ID", "菜名", "份数", "小计金额" };// 设定小票列标题 /** * @throws IOException * */ public PrintLine() throws IOException { // TODO Auto-generated constructor stub // 建立打印机连接 // socket = new Socket(PRINT_IP, PRINT_PORT); socketOut = socket.getOutputStream(); writer = new OutputStreamWriter(socketOut, "GBK"); } public static void main(String[] args) throws IOException { //小票页面 公司信息 Map<String,String> GS_INFO=new HashMap<String,String>(); GS_INFO.put("GS_Name", "XXXX科技有限公司"); GS_INFO.put("GS_Address", "武汉市解放大道2679号"); GS_INFO.put("GS_Tel", "13507115045"); GS_INFO.put("GS_Qq", "138027869"); //菜品信息 List<Map<String, Object>> PRINT_DATA = new ArrayList<Map<String, Object>>(); Map<String,Object> data1 = new HashMap<String, Object>(); data1.put("cai_name","小鸡炖蘑菇"); data1.put("cai_price","36"); PRINT_DATA.add(data1); PrintLine printLine = new PrintLine(); printLine.print(PRINT_DATA,GS_INFO,"123456789"); } /** * @param PRINT_DATA * 小票主要数据 * @param GS_INFO * 小票附带信息 * @param CAIDAN_SN * 小票号码 */ public void print(List<Map<String, Object>> PRINT_DATA,Map<String, String> GS_INFO, String CAIDAN_SN) { try { // 条码打印指令 byte[] PRINT_CODE = new byte[9]; PRINT_CODE[0] = 0x1d; PRINT_CODE[1] = 0x68; PRINT_CODE[2] = 120; PRINT_CODE[3] = 0x1d; PRINT_CODE[4] = 0x48; PRINT_CODE[5] = 0x10; PRINT_CODE[6] = 0x1d; PRINT_CODE[7] = 0x6B; PRINT_CODE[8] = 0x02; // 清除字体放大指令 byte[] FD_FONT = new byte[3]; FD_FONT[0] = 0x1c; FD_FONT[1] = 0x21; FD_FONT[2] = 4; // 字体加粗指令 byte[] FONT_B = new byte[3]; FONT_B[0] = 27; FONT_B[1] = 33; FONT_B[2] = 8; // 字体纵向放大一倍 byte[] CLEAR_FONT = new byte[3]; CLEAR_FONT[0] = 0x1c; CLEAR_FONT[1] = 0x21; CLEAR_FONT[2] = 0; // 计算合计金额 int price = 0; socketOut.write(27); socketOut.write(64); socketOut.write(FD_FONT);// 字体放大 socketOut.write(FONT_B);// 字体加粗 socketOut.write(10); writer.write(" " + GS_INFO.get("GS_Name") + " \r\n"); writer.flush();// 关键,很重要,不然指令一次性输出,后面指令覆盖前面指令,导致取消放大指令无效 socketOut.write(CLEAR_FONT); socketOut.write(10); writer.write("NO: " + CAIDAN_SN + " \r\n"); writer.write("---------------------------------\r\n"); writer.write("地址: " + GS_INFO.get("GS_Address") + "\r\n"); writer.write("联系电话: " + GS_INFO.get("GS_Tel") + " \r\n"); writer.write("---------------------------------\r\n"); writer.write(Fix_String_Lenth(1,Colum_Name[0], 6) + Fix_String_Lenth(0,Colum_Name[1], 14) + Fix_String_Lenth(1,Colum_Name[2], 4) + Fix_String_Lenth(1,Colum_Name[3], 6) + "\r\n"); for (int i = 0; i < PRINT_DATA.size(); i++) { writer.write(Fix_String_Lenth(1,i + 1 + "", 6) + Fix_String_Lenth(0,PRINT_DATA.get(i).get("cai_name") .toString(), 14) + Fix_String_Lenth(1,1 + "", 4) + Fix_String_Lenth(1,PRINT_DATA.get(i).get("cai_price") .toString(), 6) + "\r\n"); price += Integer.parseInt(PRINT_DATA.get(i).get("cai_price") .toString()); } writer.write("---------------------------------\r\n"); writer.write("本单共 " + PRINT_DATA.size() + " 道菜品,合计费用: " + price + "元\r\n"); writer.write("---------------------------------\r\n"); writer.write(" 欢 迎 品 偿 谢 谢 惠 顾\r\n"); // 下面指令为打印完成后自动走纸 writer.write(27); writer.write(100); writer.write(4); writer.write(10); // TODO: 2017/2/18 这里应该还要加入 自动切纸 的命令 writer.close(); socketOut.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 字符串长度补齐,方便打印时对齐,美化打印页面,不过中文计算好像有点问题 * * @param strs * 源字符 * @param len * 指定字符长度 * @return * @throws UnsupportedEncodingException */ public String Fix_String_Lenth(int type ,String strs, int len) { String strtemp = strs; int len1 = strs.length(); switch (type) { case 0: while (strtemp.length() < len) { strtemp += " ";} break; case 1: while (strtemp.length() < len) { strtemp += " ";} break; default: break; } return strtemp; } }

摘自

Java通过socket调用打印机实现打印小票

总结

  这里只是一个最基础的Demo,还有很多功能需要实现,比如代码里面写的自动切纸命令,还有就是一些不痛不痒的格式问题,根据不同的要求,小票的样式可能会有所改动,字体大小和间距都要可以配置才算是完成了基础功能。   如果打印机支持打印图片和二维码的话,这样打出的小票也会比较有特点,图片可以打印上店家的Logo,而二维码也可以把店家的公众号放上去,作为广告和引流作用,这样也算是一张比较有逼格的小票了。   然而要做到完美,还是需要从最基础的需求说起,比如打印丢单这个硬伤。。。

相关链接

Java 实现 POS 打印机无驱打印 Java实现控制网口打印机并完成丢单重打机制

原文首发: Java 通过 Socket 实现小票打印