简体   繁体   English

使用javax.print将纯文本文件打印到PDF打印机会导致文件为空

[英]Printing plain text files to PDF printer using javax.print results in an empty file

I need to create a pdf file from plain text files. 我需要从纯文本文件创建一个pdf文件。 I supposed that the simplest method would be read these files and print them to a PDF printer. 我以为最简单的方法是读取这些文件并将它们打印到PDF打印机。 My problem is that if I print to a pdf printer, the result will be an empty pdf file. 我的问题是,如果我打印到pdf打印机,结果将是一个空的pdf文件。 If I print to Microsoft XPS Document Writer, the file is created in plain text format, not in oxps format. 如果我打印到Microsoft XPS Document Writer,则将以纯文本格式而不是oxps格式创建文件。 I would be satisfied with a two or three step solution. 我将对两步或三步解决方案感到满意。 (Eg. converting to xps first then to pdf using ghostscript, or something similar). (例如,首先使用ghostscript或类似方法转换为xps,然后转换为pdf)。 I have tried a couple of pdf printers such as: CutePDF, Microsoft PDF writer, Bullzip PDF. 我已经尝试了几种pdf打印机,例如:CutePDF,Microsoft PDF writer,Bullzip PDF。 The result is the same for each one. 每个结果都是相同的。

The environment is Java 1.7/1.8 Win10 环境是Java 1.7 / 1.8 Win10

private void print() {

    try {
        DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;

        PrintRequestAttributeSet patts = new HashPrintRequestAttributeSet();                   
        PrintService[] ps = PrintServiceLookup.lookupPrintServices(flavor, patts);
        if (ps.length == 0) {
            throw new IllegalStateException("No Printer found");
        }
        System.out.println("Available printers: " + Arrays.asList(ps));
        PrintService myService = null;
        for (PrintService printService : ps) {
            if (printService.getName().equals("Microsoft XPS Document Writer")) { // 
                myService = printService;
                break;
            }
        }
        if (myService == null) {
            throw new IllegalStateException("Printer not found");
        }

        myService.getSupportedDocFlavors();
        DocPrintJob job = myService.createPrintJob();


   FileInputStream fis1 = new FileInputStream("o:\\k\\t1.txt");

        Doc pdfDoc = new SimpleDoc(fis1, DocFlavor.INPUT_STREAM.AUTOSENSE, null);

        HashPrintRequestAttributeSet pr = new HashPrintRequestAttributeSet();
        pr.add(OrientationRequested.PORTRAIT);
        pr.add(new Copies(1));
        pr.add(MediaSizeName.ISO_A4);
        PrintJobWatcher pjw = new PrintJobWatcher(job);
        job.print(pdfDoc, pr);
        pjw.waitForDone();
        fis1.close();

    } catch (PrintException ex) {
        Logger.getLogger(Docparser.class.getName()).log(Level.SEVERE, null, ex);
    } catch (Exception ex) {
        Logger.getLogger(Docparser.class.getName()).log(Level.SEVERE, null, ex);
    }
}


class PrintJobWatcher {

    boolean done = false;

    PrintJobWatcher(DocPrintJob job) {
        job.addPrintJobListener(new PrintJobAdapter() {
            public void printJobCanceled(PrintJobEvent pje) {
                allDone();
            }

            public void printJobCompleted(PrintJobEvent pje) {
                allDone();
            }

            public void printJobFailed(PrintJobEvent pje) {
                allDone();
            }

            public void printJobNoMoreEvents(PrintJobEvent pje) {
                allDone();
            }

            void allDone() {
                synchronized (PrintJobWatcher.this) {
                    done = true;
                    System.out.println("Printing done ...");
                    PrintJobWatcher.this.notify();
                }
            }
        });
    }

    public synchronized void waitForDone() {
        try {
            while (!done) {
                wait();
            }
        } catch (InterruptedException e) {
        }
    }
}

If you can install LibreOffice, it is possible to use the Java UNO API to do this. 如果可以安装LibreOffice,则可以使用Java UNO API进行此操作。

There is a similar example here which will load and save a file: Java Convert Word to PDF with UNO . 这里有一个类似的示例,该示例将加载和保存文件: Java使用UNO将Word转换为PDF This could be used to convert your text file to PDF. 这可用于将您的文本文件转换为PDF。

Alternatively, you could take the text file and send it directly to the printer using the same API. 或者,您可以获取文本文件,然后使用相同的API将其直接发送到打印机。

The following JARs give access to the UNO API. 以下JAR允许访问UNO API。 Ensure these are in your class path: 确保它们在您的课程路径中:

[Libre Office Dir]/URE/java/juh.jar
[Libre Office Dir]/URE/java/jurt.jar
[Libre Office Dir]/URE/java/ridl.jar
[Libre Office Dir]/program/classes/unoil.jar
[Libre Office Dir]/program

The following code will then take your sourceFile and print to the printer named "Local Printer 1". 然后将下面的代码把你sourceFile ,并打印到printer名为“本地打印机1”。

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.sun.star.beans.PropertyValue;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.view.XPrintable;

public class DirectPrintTest
{
    public static void main(String args[])
    {
        // set to the correct name of your printers
        String printer = "Local Printer 1";// "Microsoft Print to PDF";
        File sourceFile = new File("c:/projects/WelcomeTemplate.doc");

        if (!sourceFile.canRead()) {
            throw new RuntimeException("Can't read:" + sourceFile.getPath());
        }

        com.sun.star.uno.XComponentContext xContext = null;

        try {
            // get the remote office component context
            xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
            System.out.println("Connected to a running office ...");

            // get the remote office service manager
            com.sun.star.lang.XMultiComponentFactory xMCF = xContext
                    .getServiceManager();

            Object oDesktop = xMCF.createInstanceWithContext(
                    "com.sun.star.frame.Desktop", xContext);

            com.sun.star.frame.XComponentLoader xCompLoader = (XComponentLoader) UnoRuntime
                    .queryInterface(com.sun.star.frame.XComponentLoader.class,
                            oDesktop);

            StringBuffer sUrl = new StringBuffer("file:///");
            sUrl.append(sourceFile.getCanonicalPath().replace('\\', '/'));

            List<PropertyValue> loadPropsList = new ArrayList<PropertyValue>();
            PropertyValue pv = new PropertyValue();
            pv.Name = "Hidden";
            pv.Value = Boolean.TRUE;
            loadPropsList.add(pv);

            PropertyValue[] loadProps = new PropertyValue[loadPropsList.size()];
            loadPropsList.toArray(loadProps);

            // Load a Writer document, which will be automatically displayed
            com.sun.star.lang.XComponent xComp = xCompLoader
                    .loadComponentFromURL(sUrl.toString(), "_blank", 0,
                            loadProps);

            // Querying for the interface XPrintable on the loaded document
            com.sun.star.view.XPrintable xPrintable = (XPrintable) UnoRuntime
                    .queryInterface(com.sun.star.view.XPrintable.class, xComp);

            // Setting the property "Name" for the favoured printer (name of
            // IP address)
            com.sun.star.beans.PropertyValue propertyValue[] = new com.sun.star.beans.PropertyValue[2];
            propertyValue[0] = new com.sun.star.beans.PropertyValue();
            propertyValue[0].Name = "Name";
            propertyValue[0].Value = printer;

            // Setting the name of the printer
            xPrintable.setPrinter(propertyValue);

            propertyValue[0] = new com.sun.star.beans.PropertyValue();
            propertyValue[0].Name = "Wait";
            propertyValue[0].Value = Boolean.TRUE;

            // Printing the loaded document
            System.out.println("sending print");
            xPrintable.print(propertyValue);

            System.out.println("closing doc");
            ((com.sun.star.util.XCloseable) UnoRuntime.queryInterface(
                    com.sun.star.util.XCloseable.class, xPrintable))
                    .close(true);

            System.out.println("closed");

            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }
    }

}

Thank you for all. 感谢你所做的一切。 After two days struggling with various type of printers (I gave a chance to CUPS PDF printer too but I could not make it to print in landscape mode) I ended up using the Apache PDFbox. 经过两天的苦苦挣扎,使用各种类型的打印机(我也有机会使用CUPS PDF打印机,但是我无法使其以横向模式打印),最终我使用了Apache PDFbox。

It's only a POC solution but works and fits to my needs. 这只是一个POC解决方案,但可以满足我的需求。 I hope it will be useful for somebody. 我希望这对某人有用。 ( cleanTextContent() method removes some ESC control characters from the line to be printed. ) (cleanTextContent()方法从要打印的行中删除了一些ESC控制字符。)

    public void txt2pdf() {
    float POINTS_PER_INCH = 72;
    float POINTS_PER_MM = 1 / (10 * 2.54f) * POINTS_PER_INCH;
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:m.ss");

    PDDocument doc = null;
    try {
        doc = new PDDocument();

        PDPage page = new PDPage(new PDRectangle(297 * POINTS_PER_MM, 210 * POINTS_PER_MM));
        doc.addPage(page);
        PDPageContentStream content = new PDPageContentStream(doc, page);

        //PDFont pdfFont = PDType1Font.HELVETICA;
        PDFont pdfFont = PDTrueTypeFont.loadTTF(doc, new File("c:\\Windows\\Fonts\\lucon.ttf"));
        float fontSize = 10;
        float leading = 1.1f * fontSize;

        PDRectangle mediabox = page.getMediaBox();
        float margin = 20;
        float startX = mediabox.getLowerLeftX() + margin;
        float startY = mediabox.getUpperRightY() - margin;

        content.setFont(pdfFont, fontSize);
        content.beginText();
        content.setLeading(leading);
        content.newLineAtOffset(startX, startY);
        BufferedReader fis1 = new BufferedReader(new InputStreamReader(new FileInputStream("o:\\k\\t1.txt"), "cp852"));
        String inString;
        //content.setRenderingMode(RenderingMode.FILL_STROKE);
        float currentY = startY + 60;
        float hitOsszesenOffset = 0;
        int pageNumber = 1;
        while ((inString = fis1.readLine()) != null) {
            currentY -= leading;
            if (currentY <= margin) {
                content.newLineAtOffset(0, (mediabox.getLowerLeftX()-35));
                content.showText("Date Generated: " + dateFormat.format(new Date()));
                content.newLineAtOffset((mediabox.getUpperRightX() / 2), (mediabox.getLowerLeftX()));

                content.showText(String.valueOf(pageNumber++)+" lap");
                content.endText();
                float yCordinate = currentY+30;
                float sX = mediabox.getLowerLeftY()+ 35;
                float endX = mediabox.getUpperRightX() - 35;                     
                content.moveTo(sX, yCordinate);                    
                content.lineTo(endX, yCordinate);
                content.stroke();
                content.close();
                PDPage new_Page = new PDPage(new PDRectangle(297 * POINTS_PER_MM, 210 * POINTS_PER_MM));
                doc.addPage(new_Page);
                content = new PDPageContentStream(doc, new_Page);
                content.beginText();
                content.setFont(pdfFont, fontSize);
                content.newLineAtOffset(startX, startY);
                currentY = startY;
            }

            String ss = new String(inString.getBytes(), "UTF8");
            ss = cleanTextContent(ss);

            if (!ss.isEmpty()) {
                if (ss.contains("JAN") || ss.contains("SUMMARY")) {                        
                    content.setRenderingMode(RenderingMode.FILL_STROKE);
                }
                content.newLineAtOffset(0, -leading);
                content.showText(ss);
            }

            content.setRenderingMode(RenderingMode.FILL);
        }
        content.newLineAtOffset((mediabox.getUpperRightX() / 2), (mediabox.getLowerLeftY()));
        content.showText(String.valueOf(pageNumber++));
        content.endText();
        fis1.close();
        content.close();
        doc.save("o:\\k\\t1.pdf");
    } catch (IOException ex) {
        Logger.getLogger(Document_Creation.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        if (doc != null) {
            try {
                doc.close();
            } catch (IOException ex) {
                Logger.getLogger(Document_Creation.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM