添加PrinterName至PrintRequestAttributeSet时触发ClassCastException问题咨询
搞定Java打印的ClassCastException,还能指定未配置的网络打印机
嘿,我来帮你解决这个问题!你遇到的ClassCastException其实是个很典型的属性集合混用问题,咱们一步步拆解:
为啥会抛出这个异常?
你代码里把PrinterName加到了PrintRequestAttributeSet里,但这个属性根本不属于这个集合!PrinterName是用来描述打印服务本身的,属于PrintServiceAttributeSet类型,强行加到请求属性集合里就会触发类型转换异常,就是你看到的那堆堆栈信息的根源。
怎么指定系统没配置的网络打印机?
要直接用未在系统里注册的网络打印机(比如你用的IPP协议打印机),得换个思路,不能硬塞属性到错误的集合里。这里给你两种靠谱的方案:
方案1:直接通过IPP地址查找/注册打印机
Java打印API支持IPP协议,咱们可以直接根据打印机的IPP URI来定位它,代码修正如下:
import javax.print.*; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.HashPrintServiceAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.PrinterName; import java.io.ByteArrayInputStream; import java.io.InputStream; public static void main(String[] a) throws Exception { String text = " My first Printer Program"; InputStream fis = new ByteArrayInputStream(text.getBytes()); if (fis == null) { System.out.print("No File"); return; } DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; PrintRequestAttributeSet printRequestAttrs = new HashPrintRequestAttributeSet(); String targetPrinterUri = "ipp://abcd.com/ipp/ITDepartment-HP4050"; PrintService targetPrinter = null; // 先尝试从系统已识别的服务里找 PrintService[] allServices = PrintServiceLookup.lookupPrintServices(flavor, null); for (PrintService service : allServices) { if (service.getName().equals(targetPrinterUri)) { targetPrinter = service; break; } } // 如果系统没识别到,尝试手动构建服务属性(部分环境需额外配置) if (targetPrinter == null) { HashPrintServiceAttributeSet serviceAttrs = new HashPrintServiceAttributeSet(); serviceAttrs.add(new PrinterName(targetPrinterUri, null)); // 这里如果默认查找还是不行,可能需要引入第三方库或者自定义PrintService实现 targetPrinter = PrintServiceLookup.lookupPrintServices(flavor, serviceAttrs).length > 0 ? PrintServiceLookup.lookupPrintServices(flavor, serviceAttrs)[0] : null; } if (targetPrinter != null) { System.out.println("找到打印机: " + targetPrinter.getName()); DocPrintJob job = targetPrinter.createPrintJob(); Doc doc = new SimpleDoc(fis, flavor, null); job.print(doc, printRequestAttrs); fis.close(); } else { System.out.println("指定的网络打印机无法访问或未被系统识别"); } }
方案2:用对属性集合,精准查找打印机
如果你只是想通过打印机名称过滤查找,那得把PrinterName放到正确的PrintServiceAttributeSet里用于查找,而不是请求属性集合:
import javax.print.*; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.HashPrintServiceAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.PrinterName; import java.io.ByteArrayInputStream; import java.io.InputStream; public static void main(String[] a) throws Exception { String text = " My first Printer Program"; InputStream fis = new ByteArrayInputStream(text.getBytes()); if (fis == null) { System.out.print("No File"); return; } DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; // 打印请求属性:用来设置份数、纸张大小这些打印参数 PrintRequestAttributeSet printRequestAttrs = new HashPrintRequestAttributeSet(); // 打印服务属性:用来查找指定的打印机 HashPrintServiceAttributeSet serviceAttrs = new HashPrintServiceAttributeSet(); serviceAttrs.add(new PrinterName("ipp://abcd.com/ipp/ITDepartment-HP4050", null)); // 用服务属性查找打印机 PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, serviceAttrs); if (services != null && services.length > 0) { System.out.println("找到打印机: " + services[0].getName()); DocPrintJob job = services[0].createPrintJob(); Doc doc = new SimpleDoc(fis, flavor, null); job.print(doc, printRequestAttrs); fis.close(); } else { System.out.println("未找到指定的打印机,请检查地址是否正确或打印机是否在线"); } }
最后再划个重点
PrintServiceAttributeSet是找打印机用的,用来描述打印机本身的属性;PrintRequestAttributeSet是给打印任务设置参数用的,别搞混了!- 要是系统完全没识别到这个IPP打印机,可能需要额外配置Java的打印服务扩展,或者用一些第三方打印库来补充IPP的支持,不过大部分现代Java环境都能直接处理IPP地址啦。
内容的提问来源于stack exchange,提问作者Pandey Amit
相关产品推荐
相关产品推荐

