日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java指令打印 驱动打印总结 打印不需要手动选择打印机 愿你编码半生 都不会用到 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:
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轉串的驅動),效果等同于串口。

  • 串口
    需要下載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指令打印 驱动打印总结 打印不需要手动选择打印机 愿你编码半生 都不会用到的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。