首页 > 解决方案 > 使用 javax.print 将纯文本文件打印到 PDF 打印机会导致一个空文件

问题描述

我需要从纯文本文件创建一个 pdf 文件。我认为最简单的方法是读取这些文件并将它们打印到 PDF 打印机。我的问题是,如果我打印到 pdf 打印机,结果将是一个空的 pdf 文件。如果我打印到 Microsoft XPS Document Writer,该文件将以纯文本格式创建,而不是 oxps 格式。我会对两步或三步的解决方案感到满意。(例如,先转换为 xps,然后使用 ghostscript 或类似的东西转换为 pdf)。我尝试了几款 pdf 打印机,例如:CutePDF、Microsoft PDF writer、Bullzip PDF。每个人的结果都是一样的。

环境为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) {
        }
    }
}

标签: javapdfprinting

解决方案


如果您可以安装 LibreOffice,则可以使用 Java UNO API 来执行此操作。

这里有一个类似的示例,它将加载和保存文件:Java Convert Word to PDF with UNO。这可用于将您的文本文件转换为 PDF。

或者,您可以获取文本文件并使用相同的 API 将其直接发送到打印机。

以下 JAR 提供对 UNO API 的访问权限。确保这些在您的类路径中:

[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

然后,以下代码将带您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);
        }
    }

}

推荐阅读