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

时间:2018-08-21 15:31:13

标签: java pdf printing

我需要从纯文本文件创建pdf文件。我以为最简单的方法是读取这些文件并将它们打印到PDF打印机。 我的问题是,如果我打印到pdf打印机,结果将是一个空的pdf文件。如果我打印到Microsoft XPS Document Writer,则将以纯文本格式而不是oxps格式创建文件。 我将对两步或三步解决方案感到满意。 (例如,首先使用ghostscript或类似方法转换为xps,然后转换为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) {
        }
    }
}

2 个答案:

答案 0 :(得分:0)

如果您可以安装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并打印到名为“ Local Printer 1”的printer

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

}

答案 1 :(得分:0)

谢谢大家。经过两天的苦苦挣扎,使用各种类型的打印机(我也有机会使用CUPS PDF打印机,但是我无法使其以横向模式打印),最终我使用了Apache PDFbox。

这只是一个POC解决方案,但可以满足我的需求。我希望这对某人有用。 (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);
            }
        }
    }

}