Java 实现打印文件详解(附demo)

Java 实现打印文件详解

前言:公司最新需要使用到Java 打印,且项目属于C/S结构。故本文讲述的并不是Java Web打印。 说起来也比较头疼,上网查资料,发现示例都不太完善,总会有这样那样的问题。故想把自己的心得写出来供大家分享,学习!

提示:因本人项目原因,故着重实现pdf文件的打印,其他格式也会讲解!
实现打印的几种方式
  • 1.使用 Java原生自带打印功能打印
  • 2.使用 jacob 工具包打印
  • 3.使用 PDFBox 打印
Java 原生打印:

有一下几种实现方式:
实现打印对象:

  • 实现Printable接口
  • 使用工具箱自带的打印对象(Toolkit.getDefaultToolkit().getPrintJob)
  • 通过 javax.print.PrintSerivceLookup 查找定位打印对象

打印工作:
基本都是调用print();方法进行打印。
废话不多说,上代码

**实现Printable接口:**
// 此种方式必须实现 Printable接口
private void printTextAction(String printStr)
	{
		printStr = area.getText().trim(); // 打印字符串
		if (printStr != null && printStr.length() > 0)
		{
			PAGES = getPagesCount(printStr);// 分页
			// 创建打印对象
			PrinterJob myPrtJob = PrinterJob.getPrinterJob();
			// 页面格式
			PageFormat pageFormat = myPrtJob.defaultPage();
			myPrtJob.setPrintable(this, pageFormat);
			if (myPrtJob.printDialog()) // 显示打印对话框
			{
				try
				{
					myPrtJob.print(); // 开始打印
				}
				catch(PrinterException pe)
				{
					pe.printStackTrace();
				}
			}
		}
		else
		{
			JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
					, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
		}
	}

/* 分页 */
public int getPagesCount(String curStr)
	{
		int page = 0;
		int position, count = 0;
		String str = curStr;
		while(str.length() > 0)  // 文本尚未计算完毕
		{
			position = str.indexOf('\n');
			count += 1;	// 统计行数
			if (position != -1)
				str = str.substring(position + 1);  // 截取尚未计算的文本
			else
				str = "";
		}

		if (count > 0)
			page = count / 54 + 1; // 以总行数除以 54 获取总页数

		return page;				// 返回需打印的总页数
	}

Java 原生方式2

// 打印字符
private void printText2Action(String printStr)
	{
		
		if (printStr != null && printStr.length() > 0)
		{
			try
			{ 
				PAGES = getPagesCount(printStr);
				DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
				PrintService printService = PrintServiceLookup.lookupDefaultPrintService(); // 静默打印
				DocPrintJob job = printService.createPrintJob();
				PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
				DocAttributeSet das = new HashDocAttributeSet();
				Doc doc = new SimpleDoc(this, flavor, das);


				job.print(doc, pras);
			}
			catch(PrintException pe)
			{
				pe.printStackTrace();
			}
		}
		else
		{
			JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
					, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
		}
	}

原生方式3:也是本文的一个重点

// 打印文件
private void printFileAction()
	{
		// 创建一个文件选择器,构造函数存放的是当前用户路径
		JFileChooser fileChooser = new JFileChooser(SystemProperties.USER_DIR);
		// 显示文件选择对话框
		int state = fileChooser.showOpenDialog(this);
		// 选择完成
		if (state == fileChooser.APPROVE_OPTION)
		{
			// 获取选择到的文件
			File file = fileChooser.getSelectedFile();
			// 打印属性,可为空
			PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
			// 设置打印格式:自动
			DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
			// 查询所有可打印服务
			PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
			// 定位默认打印服务
			PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
			// 显示打印对话框
			PrintService service = ServiceUI.printDialog(null, 200, 200, printService
					, defaultService, flavor, pras);
			if (service != null)
			{
				try
				{
					// 创建打印作业
					DocPrintJob job = service.createPrintJob();
					FileInputStream fis = new FileInputStream(file);
					DocAttributeSet das = new HashDocAttributeSet();

					pras.add(Chromaticity.MONOCHROME);
					// 请求横向模式
					//                    pras.add(OrientationRequested.LANDSCAPE);
					// Letter大小
					pras.add(MediaSizeName.NA_LETTER);
					// European A4 paper
					pras.add(MediaSizeName.ISO_A4);
					// 请求双面
					//                    pras.add(Sides.DUPLEX);
					Doc doc = new SimpleDoc(fis, flavor, das);
					job.print(doc, pras);
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
			}
		}
	}

原生方式3:本来想用这种方式,结果发现其有一个非常严重的短板。就是txt,html,pdf等类型的文件,虽然其API提供了这些打印类型,但是发现,大部分打印机都不能正常打印,或者打印的内容为空白! 这可坑死老衲了,网上找原因,发现大家都反应这个问题,却没有解决。 因此笔者提供两种实现思路, 1.原生打印方式,图片,文字都是百分百能打印的。所以,可以将pdf转成图片,再进行打印。这无疑又绕了远路,但可以实现。 2. 采用其他方式实现打印。下文将继续介绍。

Java 打印文件之 jacob实现

优点:可以打印 excel,word 等复杂文档类型
缺点:电脑必须安装office,需要将库导入到指定位置。
所需环境:
库:jacob.dll
jar包:jacob.jar
jacob环境下载

private void doPrintDoc(List<File> fileList) {
 
		if (null == fileList || fileList.isEmpty()) {
			return;
		}
 
		// 初始化组件
		ComThread.InitSTA();
 
 
		for (File file : fileList) {
 
			if (file == null || !file.exists()) {
				return;
			}

 
			int index = file.getName().indexOf(".");
			String extName = file.getName().toUpperCase().substring(index + 1);
 
			String comApp = "Word.Application";
			String property = "Documents";
 
			if (extName.equals("DOC") || extName.equals("DOCX") || extName.equals("WPS")) {
				comApp = "Word.Application";
				property = "Documents";
			} else if (extName.equals("XLS") || extName.equals("XLSX") || extName.equals("ET")) {
				comApp = "Excel.Application";
				property = "Workbooks";
			} else if (extName.equals("PPT") || extName.equals("PPTX") || extName.equals("DPS")) {
				comApp = "PowerPoint.Application";
				property = "Presentations";
			}
 
			ActiveXComponent axc = new ActiveXComponent(comApp);
			try {
				if (!property.equals("Presentations")) {
					Dispatch.put(axc, "Visible", new Variant(false));
				}
				Dispatch document = axc.getProperty(property).toDispatch();
 
				Dispatch doc = null;
 
				if (property.equals("Presentations")) {
					doc = Dispatch.call(document, "Open", file.getAbsolutePath(), true, true, false).toDispatch();
				} else {
					doc = Dispatch.invoke(document, "Open", Dispatch.Method, new Object[] { file.getAbsolutePath() }, new int[1]).toDispatch();
				}
 
 
				Dispatch.call(doc, "PrintOut");
				Dispatch.call(doc, "Close");
				if (!property.equals("Presentations")) {
					axc.invoke("Quit", new Variant[] {});
				}
 
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				comApp = "";
				property = "";
 
			}
		}
 
		ComThread.Release();
	}

这种方式,缺点太明显,不予采纳

最后一种 PDFBox实现

所需资源:pdfbox.jar/fontbox.jar 依赖包:commons-logging.jar
下载pdfbox(完整版),含源码和commons-logging.jar

private static void print() {
		try {
			File file = new File("C:/Users/Jason/Desktop/打印测试.pdf");
			PDDocument document = PDDocument.load(file);
			// 加载成打印文件
			PDFPrintable printable = new PDFPrintable(document);
			PrinterJob job = PrinterJob.getPrinterJob();
			job.setPrintable(printable);
			job.print();
		} catch (InvalidPasswordException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (PrinterException e) {
			e.printStackTrace();
		}
	}

这种方式简直太爽了,代码简洁,功能强大!推荐大家使用这个。不需要引用动态库 ,只需加入jar包即可!

  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值