上一篇
java怎么调用打印机
- 后端开发
- 2025-08-06
- 44
在Java中,可通过
javax.print包调用打印机,先获取默认打印服务,创建对应类型的
PrintServiceLookup对象,再构造待打印内容的
Doc对象,最后
以下是关于 Java 如何调用打印机 的完整技术指南,涵盖原理、实现步骤、代码示例及常见问题解决方案:
核心机制
Java 通过 javax.print 包提供标准化打印接口,其底层依赖操作系统原生打印服务(CUPS/Windows Print Spooler),主要流程包含以下关键环节:
- 发现打印机 → 2. 获取打印服务对象 → 3. 创建打印作业 → 4. 构建打印数据流 → 5. 提交打印任务
| 核心组件 | 作用说明 |
|---|---|
PrintServiceLookup |
枚举系统中所有可用打印机 |
PrintService |
表示单个打印机的服务接口 |
DocFlavor |
定义打印数据的格式(如TEXT/HTML/IMAGE) |
PrintJob |
管理具体打印任务的生命周期 |
AttributeSet |
控制纸张大小、边距、份数等打印参数 |
分步实现详解
第一步:获取打印机列表
import javax.print.;
import javax.print.attribute.standard.;
import java.util.;
public class PrinterUtil {
// 获取所有已安装的打印机名称列表
public static List<String> listAllPrinters() {
List<String> printerNames = new ArrayList<>();
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService service : services) {
printerNames.add(service.getName());
}
return printerNames;
}
}
️ 注意:若返回空数组,需确认系统已安装物理/虚拟打印机且未禁用后台打印服务。

第二步:选择目标打印机并创建打印作业
// 根据名称精确匹配打印机(区分大小写)
private static PrintService findPrinter(String name) throws PrinterException {
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService service : services) {
if (service.getName().equalsIgnoreCase(name)) {
return service;
}
}
throw new PrinterException("未找到打印机: " + name);
}
// 创建打印作业对象
PrintJob job = service.createPrintJob();
第三步:配置打印属性(关键!)
// 设置纸张为A4横向 HashPrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet(); attrs.add(MediaSizeName.ISO_A4); // 纸张尺寸 attrs.add(OrientationRequested.LANDSCAPE); // 横向布局 attrs.add(new Copies(2)); // 打印两份 attrs.add(Chromaticity.COLOR); // 彩色打印
常用属性对照表:
| 需求 | 对应属性类及常量 |
|——————–|——————————————|
| 单面/双面 | Sides.ONE_SIDED / Sides.DUPLEX |
| 纵向/横向 | Portrait / Landscape |
| 纸张厚度 | MediaTray.THICK |
| 缩放至适合页面 | ScalingFactor.SCALE_TO_FIT |
| 页边距调整 | MarginType. (需配合自定义边距值) |
第四步:构建打印数据流(重点!)
根据 DocFlavor 类型选择不同的数据构造方式:

| 数据类型 | 典型用途 | 实现方式 |
|---|---|---|
STRING |
纯文本打印 | new SimpleDoc(textContent, flavor, null) |
URL |
网页/图片打印 | new SimpleDoc(new URL("http://example.com"), flavor, null) |
BufferedImage |
图像打印 | new SimpleDoc(image, flavor, null) |
InputStream |
PDF/PS文件打印 | new SimpleDoc(inputStream, flavor, null) |
PRINTABLE |
自定义组件打印 | 继承JComponent重写paint()方法 |
示例:打印富文本内容
// 支持HTML格式的打印(需安装支持PCL6/PostScript的打印机) DocFlavor flavor = DocFlavor.BYTE_ARRAY.TEXT; // 部分打印机需改用PDF风味 byte[] bytes = docContent.getBytes(StandardCharsets.UTF_8); Doc doc = new SimpleDoc(bytes, flavor, null);
第五步:提交打印任务
try {
job.print(doc, attrs); // 异步打印(立即返回)
// job.print(doc, attrs, true); // 同步阻塞直到完成
} catch (PrintException e) {
System.err.println("打印失败: " + e.getMessage());
} finally {
job.cancel(); // 可选:取消未完成的打印队列
}
完整代码示例:打印测试页
import javax.print.;
import javax.print.attribute.;
import javax.print.attribute.standard.;
import java.awt.;
import java.awt.print.;
import java.io.;
public class PrintDemo {
public static void main(String[] args) {
try {
// 1. 获取默认打印机
PrintService defaultPrinter = PrintServiceLookup.lookupDefaultPrintService();
if (defaultPrinter == null) {
throw new IllegalStateException("未检测到默认打印机");
}
// 2. 创建自定义打印内容(可替换为任意Component)
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("Hello Java Print!", 50, 50);
g.fillRect(100, 100, 200, 100);
}
};
// 3. 包装成Printable对象
Printable printable = new Printable() {
@Override
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) return NO_SUCH_PAGE; // 仅第一页有效
g.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
panel.print(g);
return PAGE_EXISTS;
}
};
// 4. 创建打印作业并设置属性
PrintJob job = defaultPrinter.createPrintJob();
HashPrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
attrs.add(MediaSizeName.ISO_A4);
attrs.add(OrientationRequested.PORTRAIT);
attrs.add(new Copies(1));
// 5. 执行打印
job.print(new SimpleDoc(printable, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null), attrs);
System.out.println("打印任务已提交");
} catch (Exception e) {
e.printStackTrace();
}
}
}
高级技巧与注意事项
动态页眉页脚实现
public class WatermarkPrint implements Printable {
private String watermarkText;
public WatermarkPrint(String text) { this.watermarkText = text; }
@Override
public int print(Graphics g, PageFormat pf, int page) {
if (page != 0) return NO_SUCH_PAGE;
// 绘制半透明水印
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
g.setComposite(ac);
g.setColor(Color.BLUE);
g.drawString(watermarkText, pf.getWidth()/2, pf.getHeight()/2);
return PAGE_EXISTS;
}
}
️ 常见问题排查清单
| 现象 | 可能原因及解决方案 |
|---|---|
| 打印机无响应 | 检查USB连接线/网络状态;重启打印服务;尝试更换USB端口 |
| 文字显示方框乱码 | 确保使用UTF-8编码;尝试切换DocFlavor为URL类型 |
| 图片缺失 | 确认图像格式受打印机支持(推荐PNG/JPEG);检查内存不足导致截断 |
| 多页文档只打印第一页 | 在print()方法中正确处理分页逻辑;设置Bookmark标记分割章节 |
| 彩色输出变为黑白 | 检查打印机墨盒状态;在属性集中添加Chromaticity.COLOR |
相关问答FAQs
Q1: 如何解决“No suitable printer found”异常?
A: 此错误通常由以下原因导致:① 指定的DocFlavor不被目标打印机支持;② 打印机未正确安装,解决方案:① 通过listAllPrinters()查看实际支持的打印机列表;② 尝试修改DocFlavor为通用类型(如DocFlavor.BYTE_ARRAY.AUTOSENSE);③ 确保打印机处于在线状态。

Q2: 如何实现静音模式打印(不弹出对话框)?
A: 默认情况下Java会调用操作系统的标准打印对话框,如需静默打印,需满足两个条件:① 打印机已设为默认打印机;② 在代码中显式指定所有打印参数(如纸张大小、份数等),避免触发系统弹窗,示例:
// 强制使用默认打印机且不弹窗
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
if (service instanceof StreamPrintService) {
StreamPrintService sps = (StreamPrintService) service;
OutputStream os = sps.getPrintOutputStream(attrs); // 直接获取输出流
// 向os写入数据后记得flush()和close()
} else {
throw new UnsupportedOperationException("该打印机不支持静默
