Java 实现打印文件详解

Java 实现打印文件详解

前言:公司最新需要使用到Java 打印,且项目属于C/S结构。故本文讲述的并不是Java Web打印。 说起来也比较头疼,上网查资料,发现示例都不太完善,总会有这样那样的问题。故想把自己的心得写出来供大家分享,学习!

提示:因本人项目原因,故着重实现pdf文件的打印,其他格式也会讲解!

实现打印的几种方式

  • 1.使用 Java原生自带打印功能打印
  • 2.使用 jacob 工具包打印
  • 3.使用 PDFBox 打印

Java 原生打印:

有一下几种实现方式:
实现打印对象:

  • 实现Printable接口
  • 使用工具箱自带的打印对象(Toolkit.getDefaultToolkit().getPrintJob)
  • 通过 javax.print.PrintSerivceLookup 查找定位打印对象

打印工作:
基本都是调用print();方法进行打印。
废话不多说,上代码

**实现Printable接口:**
// 此种方式必须实现 Printable接口
private void printTextAction(String printStr)
    {
        printStr = area.getText().trim(); // 打印字符串
        if (printStr != null && printStr.length() > 0)
        {
            PAGES = getPagesCount(printStr);// 分页
            // 创建打印对象
            PrinterJob myPrtJob = PrinterJob.getPrinterJob();
            // 页面格式
            PageFormat pageFormat = myPrtJob.defaultPage();
            myPrtJob.setPrintable(this, pageFormat);
            if (myPrtJob.printDialog()) // 显示打印对话框
            {
                try
                {
                    myPrtJob.print(); // 开始打印
                }
                catch(PrinterException pe)
                {
                    pe.printStackTrace();
                }
            }
        }
        else
        {
            JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
                    , JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
        }
    }

/* 分页 */
public int getPagesCount(String curStr)
    {
        int page = 0;
        int position, count = 0;
        String str = curStr;
        while(str.length() > 0)  // 文本尚未计算完毕
        {
            position = str.indexOf('\n');
            count += 1; // 统计行数
            if (position != -1)
                str = str.substring(position + 1);  // 截取尚未计算的文本
            else
                str = "";
        }

        if (count > 0)
            page = count / 54 + 1; // 以总行数除以 54 获取总页数

        return page;                // 返回需打印的总页数
    }

Java 原生方式2

// 打印字符
private void printText2Action(String printStr)
    {

        if (printStr != null && printStr.length() > 0)
        {
            try
            { 
                PAGES = getPagesCount(printStr);
                DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
                PrintService printService = PrintServiceLookup.lookupDefaultPrintService(); // 静默打印
                DocPrintJob job = printService.createPrintJob();
                PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
                DocAttributeSet das = new HashDocAttributeSet();
                Doc doc = new SimpleDoc(this, flavor, das);


                job.print(doc, pras);
            }
            catch(PrintException pe)
            {
                pe.printStackTrace();
            }
        }
        else
        {
            JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
                    , JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
        }
    }

原生方式3:也是本文的一个重点

// 打印文件
private void printFileAction()
    {
        // 创建一个文件选择器,构造函数存放的是当前用户路径
        JFileChooser fileChooser = new JFileChooser(SystemProperties.USER_DIR);
        // 显示文件选择对话框
        int state = fileChooser.showOpenDialog(this);
        // 选择完成
        if (state == fileChooser.APPROVE_OPTION)
        {
            // 获取选择到的文件
            File file = fileChooser.getSelectedFile();
            // 打印属性,可为空
            PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
            // 设置打印格式:自动
            DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
            // 查询所有可打印服务
            PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
            // 定位默认打印服务
            PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
            // 显示打印对话框
            PrintService service = ServiceUI.printDialog(null, 200, 200, printService
                    , defaultService, flavor, pras);
            if (service != null)
            {
                try
                {
                    // 创建打印作业
                    DocPrintJob job = service.createPrintJob();
                    FileInputStream fis = new FileInputStream(file);
                    DocAttributeSet das = new HashDocAttributeSet();

                    pras.add(Chromaticity.MONOCHROME);
                    // 请求横向模式
                    //                    pras.add(OrientationRequested.LANDSCAPE);
                    // Letter大小
                    pras.add(MediaSizeName.NA_LETTER);
                    // European A4 paper
                    pras.add(MediaSizeName.ISO_A4);
                    // 请求双面
                    //                    pras.add(Sides.DUPLEX);
                    Doc doc = new SimpleDoc(fis, flavor, das);
                    job.print(doc, pras);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

原生方式3:本来想用这种方式,结果发现其有一个非常严重的短板。就是txt,html,pdf等类型的文件,虽然其API提供了这些打印类型,但是发现,大部分打印机都不能正常打印,或者打印的内容为空白! 这可坑死老衲了,网上找原因,发现大家都反应这个问题,却没有解决。 因此笔者提供两种实现思路, 1.原生打印方式,图片,文字都是百分百能打印的。所以,可以将pdf转成图片,再进行打印。这无疑又绕了远路,但可以实现。 2. 采用其他方式实现打印。下文将继续介绍。

Java 打印文件之 jacob实现

优点:可以打印 excel,word 等复杂文档类型
缺点:电脑必须安装office,需要将库导入到指定位置。
所需环境:
库:jacob.dll
jar包:jacob.jar
jacob环境下载

private void doPrintDoc(List fileList) {

        if (null == fileList || fileList.isEmpty()) {
            return;
        }

        // 初始化组件
        ComThread.InitSTA();


        for (File file : fileList) {

            if (file == null || !file.exists()) {
                return;
            }


            int index = file.getName().indexOf(".");
            String extName = file.getName().toUpperCase().substring(index + 1);

            String comApp = "Word.Application";
            String property = "Documents";

            if (extName.equals("DOC") || extName.equals("DOCX") || extName.equals("WPS")) {
                comApp = "Word.Application";
                property = "Documents";
            } else if (extName.equals("XLS") || extName.equals("XLSX") || extName.equals("ET")) {
                comApp = "Excel.Application";
                property = "Workbooks";
            } else if (extName.equals("PPT") || extName.equals("PPTX") || extName.equals("DPS")) {
                comApp = "PowerPoint.Application";
                property = "Presentations";
            }

            ActiveXComponent axc = new ActiveXComponent(comApp);
            try {
                if (!property.equals("Presentations")) {
                    Dispatch.put(axc, "Visible", new Variant(false));
                }
                Dispatch document = axc.getProperty(property).toDispatch();

                Dispatch doc = null;

                if (property.equals("Presentations")) {
                    doc = Dispatch.call(document, "Open", file.getAbsolutePath(), true, true, false).toDispatch();
                } else {
                    doc = Dispatch.invoke(document, "Open", Dispatch.Method, new Object[] { file.getAbsolutePath() }, new int[1]).toDispatch();
                }


                Dispatch.call(doc, "PrintOut");
                Dispatch.call(doc, "Close");
                if (!property.equals("Presentations")) {
                    axc.invoke("Quit", new Variant[] {});
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                comApp = "";
                property = "";

            }
        }

        ComThread.Release();
    }

这种方式,缺点太明显,不予采纳

最后一种 PDFBox实现

所需资源:pdfbox.jar/fontbox.jar 依赖包:commons-logging.jar
下载pdfbox(完整版),含源码和commons-logging.jar

private static void print() {
        try {
            File file = new File("C:/Users/Jason/Desktop/打印测试.pdf");
            PDDocument document = PDDocument.load(file);
            // 加载成打印文件
            PDFPrintable printable = new PDFPrintable(document);
            PrinterJob job = PrinterJob.getPrinterJob();
            job.setPrintable(printable);
            job.print();
        } catch (InvalidPasswordException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (PrinterException e) {
            e.printStackTrace();
        }
    }

这种方式简直太爽了,代码简洁,功能强大!推荐大家使用这个。不需要引用动态库 ,只需加入jar包即可!

终于完美交差! 有问题的小伙伴可以在下方评论哦。

你可能感兴趣的:(Java核心技术,使用Java)