2017-01-21 49 views
3

以下4个问题没有帮助,因此这不是一个重复:查找,如果打印机处于联机状态并准备打印

ONETWOTHREEFOUR


我需要找到一种方法来发现我的系统报告的打印机是否可用于打印。

打印机页:

enter image description here

在图片中,打印机 “热” 可用于打印,但 “HPRT PPTII-A(USB)” 不可打印。系统显示我的是,通过使非可用的打印机阴影

使用下面的代码,我能够在系统中查找

public static List<String> getAvailablePrinters() { 
    DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE; 
    PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); 

    PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, aset); 
    ArrayList<String> names = new ArrayList<String>(); 
    for (PrintService p : services) { 
     Attribute at = p.getAttribute(PrinterIsAcceptingJobs.class); 
     if (at == PrinterIsAcceptingJobs.ACCEPTING_JOBS) { 
      names.add(p.getName()); 
     } 

    } 
    return names; 
} 

输出的所有打印机:

[HPRT PPTII-A(USB), THERMAL] 

问题是:此代码显示系统安装的所有打印机。

我需要:该列表应该只包含真正可用的打印机进行打印。在这个例子中,它应该只显示“THERMAL”,而不显示“HPRT PPTII-A(USB)”

这怎么能实现?

+0

[this] [http://stackoverflow.com/questions/1387938/how-to-check-printer-is-connected-or-not-to-your-pc-by-java)? – MaxG

+0

这不是很有帮助,只是发送给我一个文档页面,其中我不知道该怎么办...作为一个检查问题添加 – MoisesCol

回答

3

如果解决方案是Windows特有的可以,请尝试WMI4Java。这里是我的情况:

Printers list

正如你所看到的,我的默认打印机“京瓷FS-1010”是无效的(灰色),因为我简单地切换它关闭。

现在添加到您的Maven POM:

<dependency> 
    <groupId>com.profesorfalken</groupId> 
    <artifactId>WMI4Java</artifactId> 
    <version>1.4.2</version> 
</dependency> 

然后,它是那么容易,因为此列出各自的状态的所有打印机:

package de.scrum_master.app; 

import com.profesorfalken.wmi4java.WMI4Java; 
import com.profesorfalken.wmi4java.WMIClass; 

import java.util.Arrays; 

public class Printer { 
    public static void main(String[] args) { 
     System.out.println(
      WMI4Java 
       .get() 
       .properties(Arrays.asList("Name", "WorkOffline")) 
       .getRawWMIObjectOutput(WMIClass.WIN32_PRINTER) 
     ); 
    } 
} 

控制台日志如下所示:

Name  : WEB.DE Club SmartFax 
WorkOffline : False 

Name  : Send To OneNote 2016 
WorkOffline : False 

Name  : Microsoft XPS Document Writer 
WorkOffline : False 

Name  : Microsoft Print to PDF 
WorkOffline : False 

Name  : Kyocera Mita FS-1010 KX 
WorkOffline : True 

Name  : FreePDF 
WorkOffline : False 

Name  : FinePrint 
WorkOffline : False 

Name  : Fax 
WorkOffline : False 

请注意,WorkOfflineTrue为K yocera打印机。可能这是你想知道的。

而且为了过滤打印机列表现在稍加修改,以便只显示活动打印机:

  WMI4Java 
       .get() 
       .properties(Arrays.asList("Name", "WorkOffline")) 
       .filters(Arrays.asList("$_.WorkOffline -eq 0")) 
       .getRawWMIObjectOutput(WMIClass.WIN32_PRINTER) 

更新:有人问我如何让活动打印机的名称列表。好吧,这并不是那么容易,因为我刚刚提交了一个请求,shortcoming in WMI4Java。它使我们能够分析和过滤原始WMI输出,但代码仍然是相当简单:

package de.scrum_master.app; 

import com.profesorfalken.wmi4java.WMI4Java; 
import com.profesorfalken.wmi4java.WMIClass; 

import java.util.Arrays; 
import java.util.List; 
import java.util.stream.Collectors; 

public class Printer { 
    public static void main(String[] args) { 
     String rawOutput = WMI4Java 
      .get() 
      .properties(Arrays.asList("Name", "WorkOffline")) 
      .filters(Arrays.asList("$_.WorkOffline -eq 0")) 
      .getRawWMIObjectOutput(WMIClass.WIN32_PRINTER); 
     List<String> printers = Arrays.stream(rawOutput.split("(\r?\n)")) 
      .filter(line -> line.startsWith("Name")) 
      .map(line -> line.replaceFirst(".* : ", "")) 
      .sorted() 
      .collect(Collectors.toList()); 
     System.out.println(printers); 
    } 
} 

控制台输出看起来是这样的:

[Fax, FinePrint, FreePDF, Microsoft Print to PDF, Microsoft XPS Document Writer, Send To OneNote 2016, WEB.DE Club SmartFax] 
+0

以及如何获取活动打印机名称的列表? – Kerooker

+0

有趣的问题。看到我更新的答案。 – kriegaex

+0

完美。赏金是你的。不幸的是,这是一个纯Windows的解决方案。解决了我的问题(并且可能是op,因为他在窗口中提问),但对未来的用户可能不够 – Kerooker

1

的Windows解决方案,查询WMI“win32_printer”对象:

public static void main(String[] args) { 
    // select printer that have state = 0 and status = 3, which indicates that printer can print 
    ProcessBuilder builder = new ProcessBuilder("powershell.exe", "get-wmiobject -class win32_printer | Select-Object Name, PrinterState, PrinterStatus | where {$_.PrinterState -eq 0 -And $_.PrinterStatus -eq 3}"); 
    String fullStatus = null; 
    Process reg; 
    builder.redirectErrorStream(true); 
    try { 
     reg = builder.start(); 
     fullStatus = getStringFromInputStream(reg.getInputStream()); 
     reg.destroy(); 
    } catch (IOException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 
    System.out.print(fullStatus); 
} 

用于转换的InputStream为String看这里:comprehensive StackOverflow answer,或者你可以简单地使用:

public static String getStringFromInputStream(InputStream is) { 
    ByteArrayOutputStream result = new ByteArrayOutputStream(); 
    byte[] buffer = new byte[1024]; 
    int length; 
    try { 
     while ((length = is.read(buffer)) != -1) { 
      result.write(buffer, 0, length); 
     } 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 
    // StandardCharsets.UTF_8.name() > JDK 7 
    String finalResult = ""; 
    try { 
     finalResult = result.toString("UTF-8"); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 
    return finalResult; 
} 

输出:

Name       PrinterState PrinterStatus 
----       ------------ ------------- 
Foxit Reader PDF Printer     0    3 
Send to OneNote 2010      0    3 
Microsoft XPS Document Writer   0    3 
Microsoft Print to PDF     0    3 
Fax          0    3 
\\192.168.50.192\POS_PRINTER    0    3 

正如你所看到的,你现在拥有了在字符串中的工作状态中的打印机。

您可以使用您现有的方法(getAvailablePrinters())和例如添加如下内容:

ArrayList<String> workingPrinter = new ArrayList<String>(); 
    System.out.println("Working printers:"); 
    for(String printer : getAvailablePrinters()){ 
     if(fullStatus.contains("\n" + printer + " ")){ // add a newline character before the printer name and space after so that it catches exact name 
      workingPrinter.add(printer); 
      System.out.println(printer); 
     } 
    } 

现在,您将拥有一个正常工作的打印机列表。

控制台输出:

Working printers: 
Send to OneNote 2010 
Foxit Reader PDF Printer 
Microsoft XPS Document Writer 
Microsoft Print to PDF 
Fax 
\\192.168.50.192\POS_PRINTER 

当然你必须要小心这种方法的名称 - 例如如果“POS_PRINTER”在所有打印机中但不在工作打印机列表中,则如果存在名为“POS_PRINTER 1”的工作打印机,则该打印机仍然可以添加到workingPrinters列表中,因为该名称包含“\ nPOS_PRINTER”字符串...