I am planing to use Eclipse and a simple swing gui to print raw data. My bar code printer uses .prn files to print and all is encoded in the file so if I can manage to send the exact contents of the file to my printer as raw data, I can make it print the exact format I want. I can select the file and use StringBuffer to read its contents and write to a string. Now how can I manage to send this string as raw data to my printer?
Regards.
edit:
Maybe i should elaborate my question a bit; now it works,in windows using;
int ch;
FileInputStream fin = null;
try {
fin = new FileInputStream(prnfile);
while ((ch = fin.read()) != -1)
strContent.append((char) ch);
fin.close();
JOptionPane.showMessageDialog(frame, strContent);
} catch (Exception e1) {
System.out.println(e1);
}
try {
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
JOptionPane.showMessageDialog(frame, service);
DocPrintJob job = service.createPrintJob();
InputStream is = new ByteArrayInputStream(strContent.toString().getBytes());
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
Doc doc = new SimpleDoc(is, flavor, null);
job.print(doc, null);
is.close();
But when i try to run this in Ubuntu,i get only "printing cancelled,java printing " notification,and the printer does nothing (normally my printer works in ubuntu using cat xxx.prn | lpr from the terminal.Any ideas?
First, crate the printer as a raw printer as commented.
Second, as commented, read your file to a byte array, not to String to avoid decoding bytes to unicode.
And third, do not use the defaultPrintService(), look for a specific service specifying we will send a byte array to the printer (raw data) to ensure the target printer supports raw data:
DocFlavor.byteFlavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
PrintServiceAttributeSet aset = new HashPrintServiceAttributeSet();
aset.add(new PrinterName(sPrinterName, null));
PrintService[] services = PrintServiceLookup.lookupPrintServices(byteFlavor, aset);
services[0] should be a service capable to send your raw data. This had worked for me.
Related
I have a java program that prints PDFs. It uses Apache PDFBox to create a PDDocument object (from a pdf document or from a stream in some cases) and then sends it to the printer using the javax.print API:
private boolean print(File pdf, String printer)
{
boolean success = false;
try (PDDocument document = PDDocument.load(pdf))
{
PrintService[] printServices = PrinterJob.lookupPrintServices();
PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
PrinterJob job = PrinterJob.getPrinterJob();
job.setPageable(new PDFPageable(document));
// set printer
if (printer != null)
{
for (PrintService selected : printServices)
{
if (selected.getName().equals(printer))
{
printService = selected;
break;
}
}
}
job.setPrintService(printService);
job.print();
success = true;
}
catch (Exception e)
{
myLog.error("Printer error.", e);
}
return success;
}
Now I need to be able to tell the printer to staple the thing...
I am familiar with the javax.print.attributes API and use this successfully for specifying the tray or setting duplex, e.g.:
// this works fine
if (duplex != null)
{
if (duplex.equalsIgnoreCase("short"))
{
myLog.debug("Setting double-sided: Short");
attr.add(Sides.TWO_SIDED_SHORT_EDGE);
}
else
{
myLog.debug("Setting double-sided: Long");
attr.add(Sides.TWO_SIDED_LONG_EDGE);
}
}
I know there is an attribute for stapling:
attr.add(javax.print.attribute.standard.Finishings.STAPLE);
I have a Xerox Versalink B7035 with a Finisher XL attachment that fully supports stapling (i.e. it works from MS Office document settings) however the printer disregards the STAPLE attribute set from Java. I tried all other variants of staple attributes but soon found that the printer did not support ANY Java finishing attributes.
Or to put it in code, the following prints NO results:
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
Object finishings = myPrinter.getSupportedAttributeValues(Finishings.class, flavor, null);
if (finishings != null && o.getClass().isArray())
{
for (Finishings finishing : (Finishings[]) finishings)
{
System.out.println(finishing.getValue() + " : " + finishing);
}
}
After reading this and trying a few different things I concluded the printer will not accept the STAPLE attribute because the finisher is an attachment or simply because Xerox doesn't like Java or something. So now I am attempting to solve this by prepending PJL commands to the pdf before sending it, as covered here.
*PJL = Print Job Language
E.g:
<ESC>%-12345X#PJL<CR><LF>
#PJL SET STAPLE=LEFTTOP<CR><LF>
#PJL ENTER LANGUAGE = PDF<CR><LF>
[... all bytes of the PDF file, starting with '%PDF-1.' ...]
[... all bytes of the PDF file ............................]
[... all bytes of the PDF file ............................]
[... all bytes of the PDF file, ending with '%%EOF' .......]
<ESC>%-12345X
At first I assumed there would just be some method in the Apache PDFBox library to do just this, but no luck. Then I checked out the API for Ghost4J and saw nothing for prepending. Has anyone else solved this already?
Reverting to Java socket printing makes PJL a thing:
// this works, it also printed faster than javax.print when tested
private static void print(File document, String printerIpAddress, boolean staple)
{
try (Socket socket = new Socket(printerIpAddress, 9100))
{
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
byte[] bytes = Files.readAllBytes(document.toPath());
out.write(27); //esc
out.write("%-12345X#PJL\n".getBytes());
out.write("#PJL SET DUPLEX=ON\n".getBytes());
if (staple)
{
out.write("#PJL SET STAPLEOPTION=ONE\n".getBytes());
}
out.write("#PJL ENTER LANGUAGE=PDF\n".getBytes());
out.write(bytes);
out.write(27); //esc
out.write("%-12345X".getBytes());
out.flush();
out.close();
}
catch (Exception e)
{
System.out.println(e);
}
}
The needed PJL commands came from this Xerox datasheet.
It should be noted that the same PJL commands worked for two different Xerox models and a Lexmark printer, that's all I had handy to test with. Dunno if other models will want something different.
Do not need the Apache PDFBox library anymore. Or any external libraries at all.
This might work for other types of documents, aside from PDFs.
I have an application that communicates with a thermal printer in Java and
makes the thermal printer print receipts with a barcode/emphasis/different sizes and so forth using a Star tsp 100 Printer.
I can make the program print exaclty what i like but the printer is very slow. I believe the reason is that I am using non-preferable way/method of sending the byte commands.
public static void Command(byte[] bytes) throws Exception{
//The bytes array is the argument, consisting of a byte[] array such as
//byte[] Emphasis = {0x1B, 0x45}; //Which gives the text boldness.
//And Command(Emphasis); To execute the command with this method.
DocPrintJob job = PrintServiceLookup.lookupDefaultPrintService().createPrintJob();
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
Doc doc = new SimpleDoc(bytes, flavor, null);
job.print(doc, null);
}
And when i want to print a String i use this method.
public void PrintString(String s) throws Exception{
DocPrintJob job = PrintServiceLookup.lookupDefaultPrintService().createPrintJob();
System.out.println(job + " <- printer");
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
byte[] b = s.getBytes("CP437");
Doc doc = new SimpleDoc(b, flavor, null);
job.print(doc, null);
}
So i use this method to print the bulk of the String for as long as the text has the same style(Etc no additional commands necessary). So my code that prints the receipts looks somewhat like this.
PrintClass P = new PrintClass();
String Greating = "Hello";
P.Command(P.Emphasis);
P.Command(P.DoubleSize);
P.Command(P.Underline);
P.PrintString(Greating);
P.Command(P.CancelEmphasis);
P.Command(P.ResetSize);
P.Command(P.CancelUnderline);
String body = GenerateReceiptBody();
P.PrintString(body);
P.Command(P.Halfsize);
String footer = Constants.getFooter();
P.PrintString(footer);
P.Command(P.Cut);
The receipt gets printed exactly the way i want but it is a very sluggish process.
I am by no means an expert when it comes to sending POS/ESC commands. I feel however that there must be a better/faster way to do this since many applications can print a receipt with different size/barcode/style/logo without it taking 10-20 seconds.
When the receipt printer comes to a the main bulk or "body" of the receipt where everything has the same size/styling then it goes quickly, this makes me believe that the reason this is going slow for me is because i am making am creating/executing so many individual "print jobs".
So is there any faster way to send ESC/POS commands to a Thermal printer as byte commands ? In this case the thermal printer is a Star tsp 100 but i don't believe that it makes any difference for the answer.
Any answers would be very appreciated. I am sorry if this was an easy question as I am still learning how to code.
I have no idea if this will improve your printing speed, but in answer to your question about reducing the number of "print jobs", you could write all the bytes to a stream first, then send the whole stream to a single print job. I've attempted to convert your code to do this.
public static void test() throws Exception
{
ByteArrayOutputStream printData = new ByteArrayOutputStream();
printData.write(PrintClass.Emphasis);
printData.write(PrintClass.DoubleSize);
printData.write(PrintClass.Underline);
printData.write("Hello".getBytes("CP437"));
printData.write(PrintClass.CancelEmphasis);
printData.write(PrintClass.ResetSize);
printData.write(PrintClass.CancelUnderline);
printData.write(GenerateReceiptBody().getBytes("CP437"));
printData.write(PrintClass.Halfsize);
printData.write(Constants.getFooter().getBytes("CP437"));
printData.write(PrintClass.Cut);
printBytes(printData.toByteArray());
}
public static void printBytes(final byte[] bytes) throws Exception
{
DocPrintJob job = PrintServiceLookup.lookupDefaultPrintService().createPrintJob();
System.out.println(job + " <- printer");
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
Doc doc = new SimpleDoc(bytes, flavor, null);
job.print(doc, null);
}
I am creating a java application that retrieves a userId from a database, transforms it into a barcode, then sends it to a printer. I am planning to use a Zebra printer and I was wondering if anyone has experience of printing to a Zebra printer from a Java application; if so, could you share some code making this possible?
Thanks in advance,
Tumaini
There are two ways to work with Zebra printers. The first is to print as on regular printer. Java printing basics are well explained in official tutorial. End of page will treated by printer as end of sticker. The disadvantage of this approach is that all painting must be done by hands. I.e. you can't use internal printer's barcoding ability.
The second is to write ZPL commands directly to printer. Something like this:
PrintService pservice = ... // acquire print service of your printer
DocPrintJob job = pservice.createPrintJob();
String commands = "^XA\n\r^MNM\n\r^FO050,50\n\r^B8N,100,Y,N\n\r^FD1234567\n\r^FS\n\r^PQ3\n\r^XZ";
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
Doc doc = new SimpleDoc(commands.getBytes(), flavor, null);
job.print(doc, null);
The disadvantage is that you need to learn ZPL - Zebra Programming Language. Although it is simple enough, but such things as images and custom fonts could make you headache. Programming manuals are freely available on Zebra site: Part 1 and Part 2.
Not every Zebra printer has ZPL II, but then you can use EPL
EPL2 programming guide for Zebra.pdf (Link in comment section)
Code sample:
private static boolean printLabel(PrintService printService, String label) {
if (printService == null || label == null) {
System.err.println("[Print Label] print service or label is invalid.");
return false;
}
String czas = new SimpleDateFormat("d MMMMM yyyy'r.' HH:mm s's.'").format(new Date());
String command =
"N\n"+
"A50,50,0,2,2,2,N,\""+label+"\"\n"+
"B50,100,0,1,2,2,170,B,\""+label+"\"\n"+
"A50,310,0,3,1,1,N,\""+czas+"\"\n"+
"P1\n"
;
byte[] data;
data = command.getBytes(StandardCharsets.US_ASCII);
Doc doc = new SimpleDoc(data, DocFlavor.BYTE_ARRAY.AUTOSENSE, null);
boolean result = false;
try {
printService.createPrintJob().print(doc, null);
result = true;
} catch (PrintException e) {
e.printStackTrace();
}
return result;
}
I have problem with Java print service. I need to print a simple text document, to my default printer. I use HP Deskjet as my printer on Windows machine, all driver installed. This is the source code I use:
import java.io.*;
import javax.print.*;
public class PrintTest {
public static void main(String[] args) throws IOException {
File file = new File("print.txt");
InputStream is = new BufferedInputStream(new FileInputStream(file));
//Discover the default print service.
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
//Doc flavor specifies the output format of the file.
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
// Create the print job
DocPrintJob job = service.createPrintJob();
//Create the Doc
Doc doc = new SimpleDoc(is, flavor, null);
//Order to print
try {
job.print(doc, null);
} catch (PrintException e) {
e.printStackTrace();
}
is.close();
System.out.println("Printing done....");
}
}
I can see the print job on printer queue for several milisecond before its gone. But nothing get printed. I have heard it's because Java Print Service in JDK 1.6 is still buggy. But I'm not entirely sure. Any ideas why?
I know it is a very late answer but I had the same problem on Windows with PDFs (not text). It seems that printers may not be able to deal with native PDFs, so the job is accepted but nothing happens (no error too). I solved this by using a third-party lib, Apache PdfBox, and it worked like a charm.
I wrote some code example by answering a similar question https://stackoverflow.com/a/39271053/935039.
I have implemented a program, to print the document to the specific printer using IP address, printer name and running fine with out any errors and exception. A printer job is being sent from java, I am able to see this on my local printer print pool, but the page is not printing on printer.
URI myURI=null;
FileInputStream psStream=null;
try {
psStream = new FileInputStream("sample.doc");
}
catch ( FileNotFoundException e ) {
e.printStackTrace();
}
DocFlavor psInFormat = DocFlavor.BYTE_ARRAY.GIF;
Doc myDoc = new SimpleDoc( psStream, psInFormat, null );
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
PrintService[] services = PrintServiceLookup.lookupPrintServices( psInFormat, aset);
if ( services.length > 0 ) {
DocPrintJob job = services[0].createPrintJob();
try {
job.print( myDoc, aset);
}
catch ( PrintException e ){
}
}
Could you please help me out on this?
Thanks,
Srikanth Chilukuri
I found the problem.
psStream = new FileInputStream("sample.doc");
The above statement creating problem. Because It is MS Word Application, So unable to read the file using File Input Stream.
I am using POI jar and reading the doc.
POIFSFileSystem psStream = new POIFSFileSystem(new FileInputStream(filesname));
Doc myDoc = new SimpleDoc( psStream, psInFormat, null );
But Doc API is not supporing got IllegalArgumentException
Exception in thread "Main Thread" java.lang.IllegalArgumentException: data is not of declared type
at javax.print.SimpleDoc.<init>(SimpleDoc.java:82)
at com.src.print.TestPrint2.main(TestPrint2.java:67)
Could you please help me out on this.
Java Print Services allow you to "draw" pages like Swing and then send the result to a printer. It does not have knowledge of Word formats or HTML pages or similar.
Therefore you need a module which knows how to draw the contents of a doc-file to a printer to do this. I do not personally have experience with such a module.
Thanks for your response
I guess you are talking about the AWT print. This is different from Java Print Service. You can have have preformatted text data printed using a variety of options using Java Print Service(JPS)
http://docs.oracle.com/javase/1.5.0/docs/guide/jps/spec/docflavor.fm1.html#998469
The problem comes in when the file is encoded using UTF-8 and you try to print this using JPS
if its a normal ASCII file. it gets printed correctly