2017-08-03 6 views
6

J'essaie de créer un programme simple qui envoie une chaîne à une imprimante à imprimer. C'est ce que mon programme ressemble:Comment envoyer des données brutes à l'imprimante avec Java

import javax.print.Doc; 
import javax.print.DocFlavor; 
import javax.print.DocPrintJob; 
import javax.print.PrintException; 
import javax.print.PrintService; 
import javax.print.PrintServiceLookup; 
import javax.print.SimpleDoc; 

public class PrinterTest { 
    public static void main (String [] args) throws PrintException { 
    DocPrintJob job = null; 
    PrintService[] printServices = 
    PrintServiceLookup.lookupPrintServices(null, null); 
    System.out.println("Number of print services: " + printServices.length); 
    for (PrintService printer : printServices) { 
     System.out.println("Printer: " + printer.getName()); 
     if (printer.getName().contains("ZM400")) { 
      String hello = "Hello"; 
      DocFlavor flavor = DocFlavor.STRING.TEXT_PLAIN; 
      Doc doc = new SimpleDoc(hello, flavor, null); 
      job = printer.createPrintJob(); 
      job.print(doc, null); 
     } 
    } 
    } 
} 

exporter en tant que fichier jar et l'exécuter sur la ligne de commande (Windows) à l'aide:

java -jar PrinterTest.jar 

Le programme se déroule, et commence une boucle à travers tous les imprimantes installées sur l'ordinateur. Mais quand il arrive à l'imprimante Je cherche, je puis obtenir l'erreur suivante:

Exception in thread "main" sun.print.PrintJobFlavorException: invalid flavor 
    at sun.print.Win32PrintJob.print(Unknown Source) 
    at PrinterTest.main(PrinterTest.java:21) 

Pas vraiment sûr de ce que je fais mal ici, comme l'imprimante que je cherche ne montre en fait jusqu'à .

-Utiliser le lien suivant pour référence: http://docs.oracle.com/javase/7/docs/technotes/guides/jps/spec/jpsOverview.fm4.html

-Tried changer DocFlavor flavor = DocFlavor.STRING.TEXT_PLAIN-DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE, mais je reçois l'erreur IllegalArgumentException: data is not of declared type.

-Essayé de changer Doc doc = new SimpleDoc(hello, flavor, null) à Doc doc = new SimpleDoc(hello, null, null), mais il semble que vous ayez besoin d'y ajouter une saveur.

-Essayé de changer l'imprimante, comme l'imprimante d'origine que j'essayais d'appeler était une imprimante d'étiquetage, mais cela n'a pas fait de différence.

Une idée de ce que je fais mal ici? Que puis-je faire pour réparer ce code et le faire imprimer?

MISE À JOUR

Je suis arrivé à ce travail (un peu). Voilà ce que j'ai jusqu'à présent:

import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import javax.print.Doc; 
import javax.print.DocFlavor; 
import javax.print.DocPrintJob; 
import javax.print.PrintException; 
import javax.print.PrintService; 
import javax.print.PrintServiceLookup; 
import javax.print.SimpleDoc; 

public class PrinterTest { 
    public static void main (String [] args) throws PrintException, IOException { 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); 
    System.out.print("Enter the name of the printer: "); 
    String printerName = bufferedReader.readLine(); 
    System.out.print("Enter a short message of what you would like to print here: "); 
    String printerMessage = "PRINTER MESSAGE: " + bufferedReader.readLine(); 
    boolean printerCheck = false; 
    DocPrintJob job = null; 
    PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null); 
    System.out.println("Number of print services: " + printServices.length); 
    for (PrintService printer : printServices) { 
     System.out.println("Printer: " + printer.getName()); 
     if (printer.getName().contains(printerName)) { 
      InputStream inputStream = new ByteArrayInputStream(printerMessage.getBytes()); 
      DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; 
      Doc doc = new SimpleDoc(inputStream, flavor, null); 
      job = printer.createPrintJob(); 
      job.print(doc, null); 
      printerCheck = true; 
     } 
    } 
    if (printerCheck == false) { 
     System.out.println("The printer you were searching for could not be found."); 
    } 
    } 
} 

Ce que je n'ai mis la chaîne dans un flux d'entrée et changé DocFlavor.STRING.TEXT_PLAIN-DocFlavor.INPUT_STREAM.AUTOSENSE.

Mon seul hic est maintenant que rien fait impression à moins que quelque chose d'autre est envoyé à l'imprimante. Laissant ceci ici pour référence.

+1

Chemin du retour dans les âges sombres, pour obtenir une imprimante pour faire défiler la dernière page, vous deviez envoyer un octet ASCII sous forme d'alimentation '0xC' (produit sur un terminal DOS en tapant Control-L, et généralement représenté'^L'). Si votre imprimante éjecte des feuilles individuelles au lieu d'émettre un flux ininterrompu de papier plié en spirale, cette connaissance n'est probablement pas utile ... à moins que l'imprimante ait été conçue pour être rétrocompatible jusqu'aux imprimantes série à matrice de points . (Je trouverais cela carrément charmant.) –

Répondre

4

Les messages d'exception sont plutôt utiles et devraient vous aider à trouver une solution.

1) Tout d'abord, cette saveur est pas pris en charge par votre imprimante:

DocFlavor.STRING.TEXT_PLAIN; 

Cette exception dit:

Exception in thread "main" sun.print.PrintJobFlavorException: invalid flavor

Si vous regardez dans le code source de cette valeur constante, vous peut voir qu'il est déclaré comme:

public static final STRING TEXT_PLAIN = 
    new STRING ("text/plain; charset=utf-16"); 

Ainsi, la première chose que vous sh ould do vérifie quelles sont les saveurs supportées par votre imprimante.
Pour le rendre, changer le code réel:

if (printer.getName().contains("ZM400")) { 
    String hello = "Hello"; 
    DocFlavor flavor = DocFlavor.STRING.TEXT_PLAIN; 
    Doc doc = new SimpleDoc(hello, flavor, null); 
    job = printer.createPrintJob(); 
    job.print(doc, null); 
} 

par:

if (printer.getName().contains("ZM400")) { 
    Arrays.stream(printer.getSupportedDocFlavors()).forEach(f->System.out.println(f.getMediaType() + ":" + f.getMimeType() + ":" + f.getRepresentationClassName())); 
    String hello = "Hello"; 
    DocFlavor flavor = DocFlavor.STRING.TEXT_PLAIN; 
    Doc doc = new SimpleDoc(hello, flavor, null); 
    job = printer.createPrintJob(); 
    job.print(doc, null); 
} 

Avec mon imprimante, il produit la sortie suivante:

image:image/gif:[B image:image/gif:java.io.InputStream

image:image/gif:java.net.URL image:image/jpeg:[B

image:image/jpeg:java.io.InputStream image:image/jpeg:java.net.URL

image:image/png:[B image:image/png:java.io.InputStream

image:image/png:java.net.URL

application:application/x-java-jvm-local-objectref:java.awt.print.Pageable

application:application/x-java-jvm-local-objectref:java.awt.print.Printable

application:application/octet-stream:[B

application:application/octet-stream:java.net.URL

application:application/octet-stream:java.io.InputStream

Vous pouvez remarquer mon imprimante ne prend pas en charge la saveur "text/plain; charset=utf-16" non plus.

2) En changeant la saveur en DocFlavor.INPUT_STREAM.AUTOSENSE, vous n'avez plus l'exception liée au support manquant pour le DocFlavor.
Cela signifie que DocFlavor.INPUT_STREAM.AUTOSENSE est pris en charge par votre imprimante.
Mais vous rencontrez un autre problème que les données à imprimer ne correspond pas au type déclaré associé à DocFlavor.INPUT_STREAM.AUTOSENSE:

IllegalArgumentException: data is not of declared type.

En DocFlavor, la constante INPUT_STREAM.AUTOSENSE est déclarée ainsi:

public static final INPUT_STREAM AUTOSENSE = 
     new INPUT_STREAM ("application/octet-stream"); 

Cette correspond à la dernière saveur prise en charge dans la sortie précédente:

application:application/octet-stream:java.io.InputStream

An d le problème est là:

String hello = "Hello";  
... 
Doc doc = new SimpleDoc(hello, flavor, null); 

vous n'avez pas passer un InputStream mais un String.

Vous pouvez par exemple fournir un InputStream de cette façon:

String hello = "Hello";  
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; 
Doc doc = new SimpleDoc(new ByteArrayInputStream(hello.getBytes()), 
         flavor, null); 

Ou vous pouvez aussi utiliser cette saveur:

application:application/octet-stream:[B

que vous avez pas InputStream mais String en entrée: Voici la constante de saveur à utiliser:

DocFlavor.BYTE_ARRAY.AUTOSENSE 

Vous pouvez également utiliser de cette manière:

String hello = "Hello";  
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE; 
Doc doc = new SimpleDoc(hello.getBytes(), flavor, null);