java打印程序——打印图片(不带对话框)
可执行程序
前提:将要使用的打印机设为默认打印机,或者利用打印机属性进行筛选而不用lookupDefaultPrintService()指令。
import javax.imageio.ImageIO;
import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class PrintClass {
public void printImg(String fileName, int count) {
try {
//DocFlavor dof = DocFlavor.INPUT_STREAM.AUTOSENSE;
DocFlavor dof = null;
if (fileName.endsWith(".gif")) {
dof = DocFlavor.INPUT_STREAM.GIF;
} else if (fileName.endsWith(".jpg")) {
dof = DocFlavor.INPUT_STREAM.JPEG;
} else if (fileName.endsWith(".png")) {
dof = DocFlavor.INPUT_STREAM.PNG;
}
PrintService pservice = PrintServiceLookup.lookupDefaultPrintService();
//打印属性
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(OrientationRequested.PORTRAIT);
pras.add(new Copies(count));
pras.add(PrintQuality.HIGH);
pras.add(Chromaticity.MONOCHROME);
//文档属性
DocAttributeSet das = new HashDocAttributeSet();
FileInputStream fis = new FileInputStream(fileName);
// 设置打印纸张的大小(将像素转化为mm)
das.add(new MediaPrintableArea(0, 0, 110, 148, MediaPrintableArea.MM));
Doc doc = new SimpleDoc(fis, dof, das);
DocPrintJob job = pservice.createPrintJob();
job.print(doc, pras);
fis.close();
} catch (IOException ie) {
ie.printStackTrace();
} catch (PrintException pe) {
pe.printStackTrace();
}
}
}
遇到的问题及解决方法
1.不论是电脑直接打印还是java打印程序均只能将打印文档加入打印列表中但是不执行打印。
解决方法:重启电脑与打印机(可能是环境的问题)。
2.打印时java打印程序发送给打印机的文件在打印列表闪退而不执行打印。
原因:文件流出了问题。分析及解决过程如下:
原始代码(部分):
PrintService pservice = PrintServiceLookup.lookupDefaultPrintService();
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(OrientationRequested.PORTRAIT);
pras.add(new Copies(count));
pras.add(PrintQuality.HIGH);
pras.add(Chromaticity.MONOCHROME);
DocAttributeSet das = new HashDocAttributeSet();
FileInputStream fis = new FileInputStream(fileName); // (1)
///////////////////// (2) ///////////////////////
FileOutputStream fos = new FileOutputStream("E:\Software\3.jpg");
byte[] b = new byte[1024];
while((fis.read(b)) != -1){
fos.write(b);
}
fos.close();
/////////////////////////////////////////////////
//获取图像参数
BufferedImage img = ImageIO.read(fis); // (3)
int width = (int) (img.getWidth() * 2.54f /72);
int height = (int) (img.getHeight() * 2.54f /72);
System.out.println("尺寸,宽:"+width+"高"+height);
// 设置打印纸张的大小(将像素转化为mm)
das.add(new MediaPrintableArea(0, 0, width, height, MediaPrintableArea.MM));
Doc doc = new SimpleDoc(fis, dof, das);
DocPrintJob job = pservice.createPrintJob();
job.print(doc, pras);
fis.close();
分析:因为打印是文件大小仅1.22K,应该是文件流出了问题。
假设一:文件输入流读取文件时出了问题。
验证:添加代码段(2),运行后发现图片3.jpg存储正常,与原文件一样大小。故排除。
假设二:既然文件输入流读取文件时没问题,那就是读入后出现了误操作,观看程序,出了(3)处用到了文件输入流,然后就只有打印处用到了文件输入流,故可能是(3)处出现了问题。
验证:注释掉(3)处以及代码段(2)的代码,并修改后面的代码,将width与height设置为常数,发现打印正常。然后再将代码(3)放至(1)后面,解除代码段(2)的注释,执行发现不仅打印出问题,代码段(2)输出的图片3.jpg也出了问题。接着,将代码三放回原处,运行发现(3)处报错:"java.lang.NullPointerException"。由此可以看出,一个流数据只能读取一次,一旦读取后内部指针就会移到尾部,故源程序问题出在(3)上,(3)读取了文件输入流导致流数据内部指针移到了尾部无法再次读取,从而无法完成打印。
API参考:
数据流多次读取的方法:
(1)重复利用数据流来源
(2)通过mark和reset的方法