Java PrintService 怎样确认打印机接受的文档类型
来源:17golang原创
时间:2026-10-30 16:57:49 114浏览 收藏
Java 打印不是先把文件交给任意打印机,再等待失败结果。更稳妥的做法是先拿到一个 PrintService,查询它接受的 DocFlavor,再把具体纸张、份数等属性放进同一个请求上下文判断。
确认打印机接受的文档类型,先调用getSupportedDocFlavors()看能力集合,或用isDocFlavorSupported(flavor)判断一个格式;如果还带有纸张等属性,则继续调用getUnsupportedAttributes(flavor, attributes)检查组合,而不能只看格式支持。
Java 官方文档地址:https://docs.oracle.com/en/java/javase/25/docs/api/java.desktop/javax/print/PrintService.html
先分清三种判断
PrintService 描述的是打印服务的能力。文档类型由 DocFlavor 表示,它同时包含 MIME 类型和数据表示类,例如输入流、字节数组或字符流。打印服务提供三层判断:
| 要回答的问题 | 适合的 API | 结果含义 |
|---|---|---|
| 这个服务大致接受哪些文档表示 | getSupportedDocFlavors() | 返回 DocFlavor 数组 |
| 某一个格式能不能提交 | isDocFlavorSupported(flavor) | 返回 true 或 false |
| 格式和纸张等属性能否一起提交 | getUnsupportedAttributes(flavor, attrs) | null 表示没有发现不支持属性 |

这三种调用不是重复的。能力集合适合做打印服务选择或诊断,单项判断适合挡住一个确定的输入格式,组合判断则适合提交前确认本次请求的全部上下文。
列出打印服务接受的文档格式
下面的示例从系统打印服务中选出一个名称包含关键字的服务,然后打印其支持的文档格式。示例只负责表达 API 的使用关系,不把输出描述成本机已经连接的打印机结果。
import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import java.util.Arrays;
public final class PrintFlavorCatalog {
public static void main(String[] args) {
// 不传 flavor 表示先枚举可见的打印服务,而不是提前限定文档格式。
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService service : services) {
System.out.println("服务:" + service.getName());
// 返回值描述该服务可接受的文档表示类型。
DocFlavor[] flavors = service.getSupportedDocFlavors();
Arrays.stream(flavors)
.map(DocFlavor::toString)
.sorted()
.forEach(flavor -> System.out.println(" " + flavor));
}
}
}
getSupportedDocFlavors() 返回的是数组,数组中的每项都由 MIME 类型和表示类共同定义。相同的 MIME 类型,如果表示类不同,也可能是不同的 DocFlavor。因此不要只截取字符串中的 MIME 部分作为唯一键。
如果程序已经知道目标格式,直接用单项判断更清楚。例如打印 PostScript 输入流时,可以先做如下判断:
import javax.print.DocFlavor;
import javax.print.PrintService;
public final class PrintFlavorCheck {
public static boolean acceptsPostScript(PrintService service) {
// 这里的表示类是 InputStream,不能与同 MIME 的其他表示类混为一谈。
DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
return service != null && service.isDocFlavorSupported(flavor);
}
}
这个判断只说明格式本身被服务接受。官方文档特别提醒,某个格式不一定和所有打印属性都兼容,所以不要把 true 直接当成“本次打印请求一定可以提交”。
检查格式和打印属性的组合
纸张、方向、份数等属性属于另一个维度。假设我们要提交一个 PostScript 输入流,并要求使用 A4 纸,可以把它们放到 PrintRequestAttributeSet 中,再交给组合检查。
import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSizeName;
public final class PrintRequestCompatibility {
public static boolean acceptsA4PostScript(PrintService service) {
// 先固定这次请求真实使用的数据表示类型。
DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
if (service == null || !service.isDocFlavorSupported(flavor)) {
// 格式不支持时,不再把属性组合交给后续 API。
return false;
}
PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
// 属性集合表达本次打印请求,而不是服务的全部默认能力。
attributes.add(MediaSizeName.ISO_A4);
// null 表示当前格式与属性组合没有返回不支持项。
return service.getUnsupportedAttributes(flavor, attributes) == null;
}
}

getUnsupportedAttributes() 返回非 null 时,返回集合中的属性就是该请求上下文中不支持的部分。它不会替你把请求改成可提交版本;程序可以记录原因、换格式、换属性,或换一个打印服务。
把检查顺序固定在提交前
在真正创建 DocPrintJob 前,可以把策略固定成三步:先确认服务对象存在,再确认 DocFlavor,最后确认属性组合。这样每一步的失败都能给出不同提示,避免把“格式不支持”和“格式支持但 A4 组合不支持”混成同一条异常。
import javax.print.DocFlavor;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.attribute.PrintRequestAttributeSet;
public final class PrintPreflight {
public static void requireSupported(PrintService service,
DocFlavor flavor,
PrintRequestAttributeSet attributes)
throws PrintException {
// 先把调用方错误转换成有含义的失败,不让 null 进入 PrintService。
if (service == null || flavor == null) {
throw new PrintException("打印服务和文档格式不能为空");
}
if (!service.isDocFlavorSupported(flavor)) {
throw new PrintException("打印服务不接受文档格式:" + flavor);
}
// 属性集合可为 null,表示本次没有额外的请求属性。
var unsupported = service.getUnsupportedAttributes(flavor, attributes);
if (unsupported != null) {
throw new PrintException("打印属性组合不受支持:" + unsupported);
}
}
}
这里没有用 getSupportedDocFlavors() 做线性遍历,是因为业务已经知道一个候选格式,单项 API 更能表达意图。需要展示能力列表时再枚举数组;需要提交一个确定请求时,用组合检查作为最后一道边界。
几个容易误判的返回值
getSupportedDocFlavors()至少应描述一个支持的格式,但不要假设数组顺序代表优先级。isDocFlavorSupported(null)会触发空值错误,调用方应先保证格式对象存在。getUnsupportedAttributes()返回null表示没有发现不支持属性;非 null 才表示返回集合包含不支持项。- 如果传入的
DocFlavor本身不被支持,组合检查可能抛出IllegalArgumentException,所以顺序不能反过来。 - 支持格式并不代表打印机已经在线、纸盒有纸或最终作业一定物理完成;本文只覆盖 API 暴露的请求能力判断。
为什么只看 MIME 类型不够?
DocFlavor 同时包含 MIME 类型和数据表示类。输入流、字节数组等表示方式不同,打印服务可以只支持其中一种,所以应直接比较完整的 DocFlavor。
什么时候需要列出全部格式?
当用户要在多个候选格式中选择,或后台要诊断某个打印服务的能力时,使用 getSupportedDocFlavors()。如果格式已经由文件类型确定,优先使用 isDocFlavorSupported()。
属性检查能代替真实打印测试吗?
不能。它只判断打印服务是否接受给定的格式和属性组合,不承诺驱动、网络、纸张供应或设备状态。提交后仍应使用应用自己的作业状态与错误处理。
记住这条顺序即可:先选定 PrintService,再确认完整的 DocFlavor,最后用同一份属性集合检查组合。这样打印格式选择和打印任务提交之间的边界就清楚了。
-
501 收藏
-
文章 · java教程 | 1个月前 | Java · 异常处理 · 资源管理 · java try-with-resources AutoCloseable close suppressed exception501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
172 收藏
-
489 收藏
-
302 收藏
-
208 收藏
-
464 收藏
-
339 收藏
-
203 收藏
-
159 收藏
-
150 收藏
-
464 收藏
-
254 收藏
-
351 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习