Java直接控制打印机打印

本文转载自

https://blog.csdn.net/sqzhao/article/details/42519563

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

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

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

猜你喜欢

转载自blog.csdn.net/lizhengyu891231/article/details/81050086