这两天在研究Java调用打印机打印PDF文件的方法,学到了不少东西,特别来记录一下。

关于Java打印网上最多的而且也是Java正统的打印方法就是使用PrintService,一套比較标准的打印代码例如以下:

public class PrintDemo {

	public static void main(String[] args) {
JFileChooser fileChooser = new JFileChooser(); // 创建打印作业
int state = fileChooser.showOpenDialog(null);
if (state == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile(); // 获取选择的文件
// 构建打印请求属性集
HashPrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
// 设置打印格式,由于未确定类型。所以选择autosense
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();
Doc doc = new SimpleDoc(fis, flavor, das);
job.print(doc, pras);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

可是经过尝试之后,发现pdf文件并没有以pdf的格式打印出来,而是打印出乱码(也就是文件的二进制码)

初步猜想是打印机无法识别吧。于是将上面的DocFlavor改成DocFlavor.INPUT_STREAM.PDF;

那么printService[]将会为null,为什么呢?由于lookupDefaultPrintService()方法仅仅会返回支持docFlavor的打印机~

若未通过docFlavor来过滤打印机。而直接进行打印时。会报错:invalid flavor,也就是不支持该类型~

事实上我们看docFlavor。它事实上也就是发送到打印机的数据流的content-type,类似到web中,也就是不支持该content-type。那么就比較easy理解了。

后来从网上找到的解释是:

Java print service API本身支持打印, 但其并不具有解释PDF文件的能力,也就是说,用标准的Java Print API可以打印PDF文件, 但所用的打印机必须支持PDF打印标准,即打印机支持Post Script标准, 而这样的打印机通常昂贵,眼下市场上流通的便宜打印机(使用基于主机的驱动程序)基本不支持

那怎么办呢?难道我们就没办法通过Java程序来打印pdf文件了吗?无论有没有,至少要去试试吧~

发现网上并没有特别好的解决方式。

大概收集了几种:

1、比較偷懒的方法,调外挂程序来实现打印,最典型的就是Adobe Reader

2、使用PdfRenderer等第三方库先将pdf文件转换成图片,那么就能够调用PrintService来打印了

先说第一种方法吧~

首先你的电脑上得装上Adobe Reader,调用Adobe Reader来打印须要依赖acrord32这个命令

我们知道在Java中要调用命令行须要Runtime对象,详细代码例如以下:

public static boolean printPdf(String pdfPath){
try{
Runtime.getRuntime().exec("cmd.exe /C start acrord32 /P /h " + pdfPath);
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}
}

这里调用了Adobe Reader的acrord32.exe方法,以下来介绍下这个命令的參数。

acrord32.exe filename - 运行Adobe Reader,而且浏览PDF

其它还支持的參数有:

AcroRd32.exe /p filename - 运行Adobe Reader,而且打印一个PDF文件

AcroRd32.exe /t path printername drivername portname

初始化Adobe Reader, 不弹出打印对话框。然后结束打印

/t 命令所需的四个參数有

path - 打印文件路径

printername - 打印机名字

drivername - 打印机驱动名字

portname - 打印机端口

其它的參数:

/n 开一个新的Adobe Reader, 虽然有Adobe Reader已经打开 (静默打印不用)

/s 打开一个Adobe Reader不开splash screen

/o 打开一个Adobe Reader不开打开文件对话框

/h 以最小化方式打开一个Adobe Reader (静默打印使用)

关于这两天研究Java打印pdf方法的记录的更多相关文章

  1. Java 打印PDF文档的3种情况

    以下内容归纳了通过Java程序打印PDF文档时的3种情形.即: 静默打印 显示打印对话框打印 打印PDF时自定义纸张大小 使用工具:Spire.PDF for Java Jar导入: 方法1:通过官网 ...

  2. java读取pdf文本转换html

    补充:一下代码基于maven,现将依赖的jar包单独导出 地址:pdf jar 完整代码地址 也就两个文件 java读取pdf中的纯文字,这里使用的是pdfbox工具包 maven引入如下配置 < ...

  3. 使用Java线程并发库实现两个线程交替打印的线程题

    背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...

  4. [Java并发]实现两个线程交替打印奇偶数(volatile+yield实现)

    解题思路 实现一个类OddEven 有一个打印奇数的方法,有一个打印偶数的方法. 类中有一个volatile变量 ,用来控制当前状态是该哪个方法打印. 方法中打印每个数前首先判断volatile变量的 ...

  5. 深入研究Java类载入机制

    深入研究Java类载入机制   类载入是Java程序运行的第一步,研究类的载入有助于了解JVM运行过程,并指导开发人员採取更有效的措施配合程序运行. 研究类载入机制的第二个目的是让程序能动态的控制类载 ...

  6. 安卓打印实现打印pdf文档

    先声明一下,此处的打印非pos打印机打印和蓝牙打印机打印,如果想查找打印小票的pos打印机请进入下面的传送门,蓝牙打印目前没做过,有做过的请指教. pos打印机传送门: 1. https://www. ...

  7. Java 打印程序设计实例

    3.1 打印文本 3.1.1 应用场景 假设我们需要打印一个窗体的某个文本编辑域(可能只有几行,也可能包含多页)的内容,并且每页最多打印 54 行,如何实现呢? 3.1.2 解决方法 基本思路如下:首 ...

  8. 深入研究java.lang.ThreadLocal类 (转)

    深入研究java.lang.ThreadLocal类     一.概述   ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thr ...

  9. 深入研究Java类装载机制

    目录 1.为什么要研究java类装在机制? 2.了解类装载机制,对于我们在项目开发中有什么作用? 3.装载实现细节. 4.总结 一.为什么药研究Java类装载机制 java类加载机制,便于我们使用自定 ...

随机推荐

  1. laravel5通过auth.attempt事件加入登陆验证码

    <?php namespace WangDong\Http\Controllers\Auth; use Illuminate\Http\Exception\HttpResponseExcepti ...

  2. Access自动编号的初始值设置及重置编号 转

    方法如下: ALTER TABLE tableName ALTER COLUMN Id COUNTER (100, 5) 其中:tableName为要修改的表名,Id为自动编号列,100为初始值,5为 ...

  3. Bootstrap_Javascript_手风琴

    触发手风琴可以通过自定义的 data-toggle 属性来触发.其中data-toggle值设置为 collapse,data-target="#折叠区标识符". 第一步,设计一个 ...

  4. 马的遍历问题-回溯法应用-ACM

    马的遍历问题 在n*m的棋盘中,马只能走“日” 字.马从位置(x,y)处出发,把棋盘的每一格都走一次,且只走一次.找出所有路径. 问题解的搜索空间? 棋盘的规模是n*m,是指行有n条边,列有m条边. ...

  5. [Python]更加Pythonic的多个List合并和Python的安利

    原题: https://segmentfault.com/q/1010000005904259 问题: 倘若存在 L=[ [1,2,3],[4,5,6],[7,8,9]] 这样的列表,如何把合并成[1 ...

  6. WWDC2014之App Extensions学习笔记

    一.关于App Extensions extension是iOS8新开放的一种对几个固定系统区域的扩展机制,它可以在一定程度上弥补iOS的沙盒机制对应用间通信的限制. extension的出现,为用户 ...

  7. run_command函数分析

    一.概述 位置:common/main.c 功能:根据传入参数(命令),在命令存储区(.u_boot_cmd)中查找对应的命令,找到命令并调用对应的函数执行 流程: 二.分析 1.函数说明信息 /** ...

  8. 转: 静态模式makefile中$(cobjs): $(obj)/%.o: $(src)/%.c

    4.12 静态模式静态模式规则是这样一个规则:规则存在多个目标,并且不同的目标可以根据目标文件的名字来自动构造出依赖文件.静态模式规则比多目标规则更通用,它不需要多个目标具有相同的依赖.但是静态模式规 ...

  9. ubuntu下配置protobuf

    http://blog.csdn.net/guoyilongedu/article/details/17093811 最近想研究protobuf ,尝试了很多次都没有成功,我用的是ubuntu,在虚拟 ...

  10. 转 一些shell经验

    http://www.cnblogs.com/xublogs/archive/2010/03/16/2292254.html http://www.cnblogs.com/stephen-liu74/ ...