How to send raw data to printer with Java

Viewed 9018

I am trying to create a simple program that sends a string to a printer to print. This is what my program looks like:

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);
        }
    }
  }
}

I export this as a jar file and run it on command line (Windows) using:

java -jar PrinterTest.jar

The program runs, and starts looping through all of the installed printers on the computer. But when it gets to the printer I am looking for, I then get the following error:

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

Not really sure what I'm doing wrong here, as the printer that I am searching for does in fact show up.

-Using the following link for reference: http://docs.oracle.com/javase/7/docs/technotes/guides/jps/spec/jpsOverview.fm4.html

-Tried changing DocFlavor flavor = DocFlavor.STRING.TEXT_PLAIN to DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE, but I get the error IllegalArgumentException: data is not of declared type.

-Tried changing Doc doc = new SimpleDoc(hello, flavor, null) to Doc doc = new SimpleDoc(hello, null, null), but it seems like you need to add a flavor there.

-Tried changing the printer, as the original printer I was trying to call was a labeling printer, but that did not make a difference.

Any idea what I'm doing wrong here? What can I do to fix this code and make it print?

UPDATE

I got this to (somewhat) work. This is what I have so far:

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.");
    }
  }
}

What I did was put the string into an input stream, and changed DocFlavor.STRING.TEXT_PLAIN to DocFlavor.INPUT_STREAM.AUTOSENSE.

My only hiccup now is that nothing actually prints unless something else is sent to the printer. Leaving this here for now for reference.

1 Answers
Related