前言:
1、需要少量硬件知识 需要懂IO流
2、作为总结 内容有点多
3、打印机分为串口打印、网口打印、并口打印等,一般情况 只有指令打印才需要去区分,而驱动打印的话 ,只需要知道打印机名字就好了 Printable+awt+javax.print
4、一般情况 热敏打印机 驱动和指令两种打印方式 速度基本差不多 因为都很快 ;而老旧的针式打印机 驱动打印会特别慢,或者热敏打印 但不适合装驱动时 需要指令打印。

一、驱动打印:

// google的core 包,用于网址转二维码 不需要相应代码可删除
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;import javax.imageio.ImageIO;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.standard.PrinterName;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.awt.print.*;
import java.io.*;
/**
*@author by qkj
*/
public class PrintDemo {public static void main(String[] args){// 可以理解为新建一个打印面板Book book = new Book();PageFormat pf = new PageFormat();pf.setOrientation(1);// 打印纸张 以及设置规格等Paper p = new Paper();p.setSize(250, 750);p.setImageableArea(0.0D, 0.0D, 250, 750);pf.setPaper(p);Printable printable = new Printable(){@Overridepublic int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {//Graphics是抽象类 ,多态 转型Graphics2D g2 = (Graphics2D)graphics;BufferedImage logo = null;try {// 图片的路径 这里是取的项目根目录 绝对路径//(以及某些需要打包成exe的java项目 一定要用绝对路径 不能取src底下根目录)String strBmpFile = System.getProperty("user.dir")+ "\\logo1.bmp";InputStream is = new FileInputStream(strBmpFile);logo = ImageIO.read(is);} catch (IOException e) {e.printStackTrace();}// 打印图片g2.drawImage(logo, (BufferedImageOp)null, 25, 10);//打印文本g2.drawString(" - - - - - - - - - - - - - - - - - -  ", 20.0F, 100.0F);g2.drawString("测试: 你好", 25.0F, 115.0F);g2.drawString("测试: 你好" , 25.0F, 130.0F);g2.drawString("测试: 你好" , 25.0F, 145.0F);g2.drawString("测试: 你好" , 25.0F, 160.0F);g2.drawString("测试: 你好" , 25.0F, 175.0F);g2.drawString("测试: 你好" , 25.0F, 190.0F);g2.drawString("测试: 你好" , 25.0F, 205.0F);g2.drawString("测试: 你好:测试", 25.0F, 220.0F);g2.drawString("测试: 你好:测试" , 25.0F, 235.0F);g2.drawString("测试: 你好时间:10:00" , 25.0F, 250.0F);g2.drawString("测试: 你好时间:10:00" , 25.0F, 265.0F);// 网址转二维码BufferedImage image = null;try {BitMatrix byteMatrix = new MultiFormatWriter().encode(new String("www.baidu.com".getBytes(), "iso-8859-1"),BarcodeFormat.QR_CODE, 175, 175);int width = byteMatrix.getWidth();int height = byteMatrix.getHeight();final int BLACK = 0xFF000000;final int WHITE = 0xFFFFFFFF;image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, byteMatrix.get(x, y) ? BLACK : WHITE);}}} catch (WriterException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}// 图片转单色位 需要则取之 某些老旧针式打印机中 指令打印只能打单色位bmp图片String path = System.getProperty("user.dir") + "\\code.bmp";File file = new File(path);int h = 0;int w = 0;int[] pixels = new int[0];try {OutputStream fileOutputStream = new FileOutputStream(file);ImageIO.write(image, "bmp", fileOutputStream);fileOutputStream.close();BufferedImage sourceImg = ImageIO.read(new File(path));h = sourceImg.getHeight();w = sourceImg.getWidth();pixels = new int[w * h];PixelGrabber pixelGrabber = new PixelGrabber(sourceImg, 0, 0, w, h, pixels, 0, w);pixelGrabber.grabPixels();} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}int gray;for (int j = 0; j < h; j++) {for (int i1 = 0; i1 < w; i1++) { // 由红,绿,蓝值得到灰度值gray = (int) (((pixels[w * j + i1] >> 16) & 0xff) * 0.8);gray += (int) (((pixels[w * j + i1] >> 8) & 0xff) * 0.1);gray += (int) (((pixels[w * j + i1]) & 0xff) * 0.1);pixels[w * j + i1] = (255 << 24) | (gray << 16) | (gray << 8) | gray;}}MemoryImageSource imageSource = new MemoryImageSource(w, h, pixels, 0, w);Image newimage = Toolkit.getDefaultToolkit().createImage(imageSource);BufferedImage bufImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);bufImage.createGraphics().drawImage(newimage, 0, 0, null);try {ImageIO.write(bufImage, "BMP", new File(path));} catch (IOException e) {e.printStackTrace();}g2.drawImage(bufImage, (BufferedImageOp)null, 15, 335);return 0;}};book.append(printable, pf);// 获取打印服务对象PrinterJob job = PrinterJob.getPrinterJob();job.setPageable(book);try {HashAttributeSet hs = new HashAttributeSet();// 实际使用一定要写配置文件 不能直接写死打印机名字 //打印机名字为控制面板-打印机 属性里面的全名,例如A打印机 使用的是B打印机通用驱动,名字以B为准String printerName = "TP805";hs.add(new PrinterName(printerName, null));PrintService[] pss = PrintServiceLookup.lookupPrintServices(null, hs);if (pss.length == 0 /*|| pss1.length == 0*/) {System.out.println("无法找到打印机:" + printerName);}// 设置打印类job.setPageable(book);//添加指定的打印机job.setPrintService(pss[0]);// 打印job.print();} catch (PrinterException e) {e.printStackTrace();}}
}

二、难点:指令打印
首先需要知道:打印机有网口(类似于网线口 但是通常都是比网线口小一点),串口 (COM 上4下5 九个点 梯形状),并口(LPT 比串口长很多的梯形状),USB口 …
有的电脑主机可能没有串口,那么需要使用USB转串线 (电脑需要安装usb转串的驱动),效果等同于串口。

  1. 串口
    需要下载RXTX一个jar包,两个dll文件,dll严格区分电脑32,,64位!并将其放入对应目录下。
    优点:指令打印速度远大于驱动打印;
    缺点:需要配置环境,如果用户规模大 且用户完全不懂技术 需要自行考虑时间与后果 是否能够承受

package printDemo;
// rxtx包
import gnu.io.*;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.TooManyListenersException;
/**
*@author by qkj
*/
public class NewPrintDemo implements SerialPortEventListener {private static boolean isOpen = false;static Set<CommPortIdentifier> portList = new HashSet<CommPortIdentifier>();final static String appName = "MyApp";private static InputStream is;private static OutputStream os;private static SerialPort serialPort;byte[] readBuffer = new byte[100];static OutputStream outputStream;public static void main(String[] args) {Enumeration tempPortList;  //枚举类CommPortIdentifier portIp;tempPortList = CommPortIdentifier.getPortIdentifiers();while (tempPortList.hasMoreElements()) {//在这里可以调用getPortType方法返回端口类型,串口为CommPortIdentifier.PORT_SERIALportIp = (CommPortIdentifier) tempPortList.nextElement();portList.add(portIp);int portType = portIp.getPortType();// 得到串口类型,并且串口名字为 XXX  com6表示 串口接入电脑的com6口,(在设备管理器可查看)if (portType == (CommPortIdentifier.PORT_SERIAL) && portIp.getName().equals("COM6")) {try {// com口以及超时时间(毫秒) // 注:这里很可能报错 unknown application 实际意义为 串口打开失败 目前通过测试 //已知原因有: 1.串口占用,例如你写两个demo程序,另一个还开着占用了该串口 一定会报错;//2.串口识别失败,比如插入电脑 没反应 或者串口坏了 这涉及到硬件问题 无法深一步解释serialPort = (SerialPort) portIp.open("COM6", 5000);// 显而易见 9600是打印机默认波特率 serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);// 输出流outputStream = serialPort.getOutputStream();OutputStreamWriter writer = new OutputStreamWriter(SimpleWrite.outputStream, "UTF-8");byte[] cmd = new byte[3];cmd[0] = 0x1B;cmd[1] = 'J';cmd[2] = 0x0D;outputStream.write(cmd);outputStream.close();//    SimpleWrite.outputStream.write(cmd);//     writer.write("\n\n");//     writer.write(" 单号:11111\n");//图片打印失败,打印出来内容实际为图片用文本格式打开的乱码内容,暂时不清楚怎么通过该IO//方式打印 不知道是自身对IO理解错误还是和打印机本身有关,但需要注意的是 很多针式老款打                        //印机 只能打印单色位图片,一定要严格转成单色位// ImageIO.write(read, "jpg", outputStream);} catch (Exception e) {e.printStackTrace();}}}}public Set<CommPortIdentifier> getPortList() {Enumeration tempPortList;  //枚举类CommPortIdentifier portIp;tempPortList = CommPortIdentifier.getPortIdentifiers();/*不带参数的getPortIdentifiers方法获得一个枚举对象,该对象又包含了系统中管理每个端口的CommPortIdentifier对象。* 注意这里的端口不仅仅是指串口,也包括并口。* 这个方法还可以带参数。* getPortIdentifiers(CommPort)获得与已经被应用程序打开的端口相对应的CommPortIdentifier对象。* getPortIdentifier(String portName)获取指定端口名(比如“COM1”)的CommPortIdentifier对象。*/while (tempPortList.hasMoreElements()) {//在这里可以调用getPortType方法返回端口类型,串口为CommPortIdentifier.PORT_SERIALportIp = (CommPortIdentifier) tempPortList.nextElement();portList.add(portIp);}return portList;}public boolean openSerialPort(CommPortIdentifier portIp, int delay) {try {serialPort = (SerialPort) portIp.open(appName, delay);/* open方法打开通讯端口,获得一个CommPort对象。它使程序独占端口。* 如果端口正被其他应用程序占用,将使用 CommPortOwnershipListener事件机制,传递一个PORT_OWNERSHIP_REQUESTED事件。* 每个端口都关联一个 InputStream 和一个OutputStream。* 如果端口是用open方法打开的,那么任何的getInputStream都将返回相同的数据流对象,除非有close 被调用。* 有两个参数,第一个为应用程序名;第二个参数是在端口打开时阻塞等待的毫秒数。*/} catch (PortInUseException e) {return false;}try {is = serialPort.getInputStream();/*获取端口的输入流对象*/os = serialPort.getOutputStream();/*获取端口的输出流对象*/} catch (IOException e) {return false;}try {serialPort.addEventListener(this);/*注册一个SerialPortEventListener事件来监听串口事件*/} catch (TooManyListenersException e) {return false;}serialPort.notifyOnDataAvailable(true);/*数据可用*/try {/*设置串口初始化参数,依次是波特率,数据位,停止位和校验*/serialPort.setSerialPortParams(4800, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);} catch (UnsupportedCommOperationException e) {return false;}return true;}public boolean closeSerialPort() {if (isOpen) {try {is.close();os.close();serialPort.notifyOnDataAvailable(false);serialPort.removeEventListener();serialPort.close();isOpen = false;} catch (IOException e) {return false;}}return true;}public boolean sendMessage(String message) {try {os.write(message.getBytes());} catch (IOException e) {return false;}return true;}@Overridepublic void serialEvent(SerialPortEvent event) {/** 此处省略一下事件,可酌情添加*  SerialPortEvent.BI:/*Break interrupt,通讯中断*  SerialPortEvent.OE:/*Overrun error,溢位错误*  SerialPortEvent.FE:/*Framing error,传帧错误*  SerialPortEvent.PE:/*Parity error,校验错误*  SerialPortEvent.CD:/*Carrier detect,载波检测*  SerialPortEvent.CTS:/*Clear to send,清除发送*  SerialPortEvent.DSR:/*Data set ready,数据设备就绪*  SerialPortEvent.RI:/*Ring indicator,响铃指示*  SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,输出缓冲区清空*/if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {/*Data available at the serial port,端口有可用数据。读到缓冲数组,输出到终端*/try {while (is.available() > 0) {is.read(readBuffer);//收到的数据再此,可视情况处理}} catch (IOException e) {}}}}

2.网口,和串口打印基本相似,需要在电脑配置相应的IP地址,换成socket获取输出流,指令数组放入输出流即可

3.补充 :通过其它方式:
有部分打印机厂商会提供dll文件以及相应demo, dll里面也是通过指令方式打印,并且会提供打印位图的方法,因为指令大多数与爱普生的一致,所以大部分打印机都是通用的,但可能存在部分兼容性问题,比如打印不全 ,没出问题还好 出现问题很难解决!! 如果有需要可以直接联系相关打印机厂商,涉及商业层面 代码以及dll不公开!

java指令打印 驱动打印总结 打印不需要手动选择打印机 愿你编码半生 都不会用到相关推荐

  1. mac 爱普生打印机驱动_高效打印企业首选 爱普生M2178黑白多功能一体机评测

    提到打印机相信每一个公司都配备了一台,因为它是日常办公中不可缺少.尽管现在很多的工作流程都已经可以在线上执行,且提倡无纸化办公,但很多重要的材料还是需要打印出来存档.签字.因此打印机还是一个非常必要的 ...

  2. Windows打印体系结构之打印驱动框架

    庐山烟雨浙江潮,未到千般恨不消.到得原来无别事,庐山烟雨浙江潮. 1.2.Windows打印驱动框架 Windows的打印驱动从总体架构上来说,包括一个渲染组件和一个配置组件.我们可以回想一下最开始的 ...

  3. java中使用pdfBox打印pdf;java web打印pdf;静默打印;jar程序打包成exe文件;exe4j的使用

    java编写打印控件 web打印一直是个棘手的问题,市面上的第三方打印插件也是贵的离谱,这里给出一个可行的解决方案. SpringBoot项目的web服务,实现的功能: 获取电脑可用的打印机列表 设置 ...

  4. java+selenium+autoIt 实现下载(打印)功能

    java+selenium+autoIt 实现下载(打印)功能 selenium是一个开源的自动化测试框架,它可以模拟用户对浏览器的操作,进行自动化的测试.但是,它不仅仅只能用来做测试. AutoIt ...

  5. 关于《Foxit Phantom的完美破解》的一点补充——打印驱动破解

    [破解作者] solo_lxy [使用工具] OD,IDA Pro [软件名称] Foxit Phantom 1.0.2.1123 [软件简介] Foxit Phantom是一个商业级的PDF应用软件 ...

  6. windows无法访问指定设备_打印驱动架构之windows

    Windows打印驱动框架 Windows的打印驱动从总体架构上来说,包括一个渲染组件和一个配置组件.我们可以回想一下最开始的总体架构图. 渲染组件就是负责将应用程序传来的每一页的绘制命令(GDI命令 ...

  7. android+源码usb驱动,安卓打印驱动最全驱动源码库(usbSerialForAndroid)

    [实例简介] 此项目用于安卓小票打印驱动.(稳定版)已用于实际项目 支持: USB转串口线.纯串口阵脚打印线.纯USB打印线.Cp21xx.USB CDC/ACM serial.FTDI Serial ...

  8. java lodop打印_Java的云打印Lodop

    Lodop是一款专业的WEB打印控件,其设计目标是简单易用.功能足够强大,开创WEB打印开发的新局面. Lodop设计者对WEB下的打印开发任务进行了分类汇总,高度抽象,设计出仅用几个功能函数,就可实 ...

  9. java调adobe打印_Java报表工具打印方案集锦 | 改变自己

    本文试图对市面上流行的纯java实现的web报表工具,jasperreport . stylereport .杰表.润乾报表.快逸.finererport为例,分析各报表工具采用的web打印技术的异同 ...

  10. RK3399 GMAC驱动失败,打印如下log,DMA engine initialization failed 原因

    公众号 欢迎扫码关注本人微信公众号:公众号上分享更多嵌入式知识和资料,分享个人学习嵌入式的心得体会.欢迎大家一起来玩呀. RK3399 GMAC驱动失败,打印如下log,DMA engine init ...

最新文章

  1. 使用Nginx-rtmp-module搭建hls直播
  2. 她在博士阶段破釜沉舟转换研究方向后,发表了32篇SCI
  3. TeXworks 0.4.5 发布,TeX 编辑器
  4. 云原生 - Istio可观察性之分布式跟踪(三)
  5. python类实例化_python基础8之类的实例化过程剖析
  6. 常用数据结构算法 c++模板实现
  7. 三星Galaxy S22系列快充规格曝光:只可比肩iPhone 13Pro Max
  8. Sentinel流控规则_关联_分布式系统集群限流_线程数隔离_削峰填谷_流量控制_速率控制_服务熔断_服务降级---微服务升级_SpringCloud Alibaba工作笔记0035
  9. 关于未来IOT和移动APP集成的五个预言
  10. 世界各个地区WIFI 2.4G及5G信道划分表(附无线通信频率分配表)
  11. 阿里云DataV数据展示的一些sql写法
  12. 第一天计算机谁发明的,世界公认三大天才,尼古拉特斯拉是当之无愧的第一天才...
  13. 身体健康是第一生产力 --- 我看央视主持人李咏早逝
  14. 微型计算机登录密码忘记了怎么办,一种基于微型计算机的密码锁的制作方法
  15. 中国城市应急联动系统发展模式及战略咨询研究报告2021-2027年
  16. Html中img自带属性有哪些,HTMLIMG标签的属性是有哪些?了解IMG标签的用法
  17. [js操作(转)]在IE下js操作本地文件相关方法
  18. R语言用LOESS(局部加权回归)季节趋势分解(STL)进行时间序列异常检测
  19. [译]Kotlin的独门秘籍Reified实化类型参数(上篇)
  20. 用c语言构造真值表,构造命题公式的真值表--biaobiao88

热门文章

  1. 数据分类算法-朴素贝叶斯
  2. java写出麻将和牌的算法,麻将胡牌算法
  3. 华为手机root的最简单方法教程!附专用root工具!详细
  4. uni-app实战之社区交友APP(12)文章和话题API开发
  5. 小白学java-JVM知识点总结
  6. js制作flash文件进度条
  7. win10系统更新后打开chrome浏览器几秒后自动闪退
  8. WeLink协作文档:办公协作再快一档
  9. HTML5百度地图规划路线,百度手机地图手动设置地图路线的方法 路线选择方法
  10. VSCode 新版 HTML文件 英文感叹号 + Tab 没有出现模板 解决方法