2013-12-12 26 views
2

我正在嘗試使用java.awt.print包打印PDF文檔。我這樣做是通過創建一個Printable對象來完成文件的簡短轉換(前一種技術是從不同的主題中導出的)。PDF Renderer導致零分差

private static void printDocument(File finalFile, PrintService printer, String name) throws PrinterException { 

    System.out.println(String.format("Starting %s document", name)); 

    FileInputStream fileInputStream = null; 
    try { 

     fileInputStream = new FileInputStream(finalFile); 
     byte[] pdfContent = new byte[fileInputStream.available()]; 
     fileInputStream.read(pdfContent, 0, fileInputStream.available()); 
     ByteBuffer buffer = ByteBuffer.wrap(pdfContent); 
     final PDFFile pdfFile = new PDFFile(buffer); 

     //Create Printable object in preparation for printing 
     Printable printable = new Printable() { 

      public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { 

       int pagenum = pageIndex + 1; 
       if ((pagenum >= 1) && (pagenum <= pdfFile.getNumPages())) { 

        Graphics2D graphics2D = (Graphics2D) graphics; 
        PDFPage page = pdfFile.getPage(pagenum); 

        Rectangle imageArea = new Rectangle((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY(), 
          (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableHeight()); 

        graphics2D.translate(0, 0); 
        PDFRenderer pdfRenderer = new PDFRenderer(page, graphics2D, imageArea, null, null); 

        try { 
         page.waitForFinish(); 
         pdfRenderer.run(); 
        } 
        catch (InterruptedException e) { 
         e.printStackTrace(); 
         throw new PrinterException("Oh noes!"); 
        } 
        return PAGE_EXISTS; 
       } 
       else { 
        return NO_SUCH_PAGE; 
       } 
      } 
     }; 

     PrinterJob printJob = PrinterJob.getPrinterJob(); 

     printJob.setPrintService(printer); 

     PageFormat pageFormat = printJob.defaultPage(); 
     Book book = new Book(); 
     book.append(printable, pageFormat, pdfFile.getNumPages()); 
     printJob.setPageable(book); 

     Paper paper = new Paper(); 
     paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight()); 
     pageFormat.setPaper(paper); 


     PrintRequestAttributeSet pset = new HashPrintRequestAttributeSet(); 
     printJob.setJobName(finalFile.getName() + 
       "|" + String.valueOf(1) + 
       "|" + ("T")); 

     printJob.print(pset); 
    } 

    catch (Exception e) { 
     e.printStackTrace(); 
     throw new PrinterException(); 
    } 
    finally { 
     if (fileInputStream != null) { 
      try { 
       fileInputStream.close(); 
      } 
      catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    System.out.println(String.format("Finished %s document", name)); 
} 

某些特定情況下的PDF文件沒有反應良好這個轉換過程中,沒有對pdfRenderer.run();符合該堆棧跟蹤:

java.lang.ArithmeticException:/by zero 
    at com.sun.pdfview.pattern.PatternType1$Type1PaintContext.getRaster(PatternType1.java:354) 
    at sun.java2d.pipe.AlphaPaintPipe.renderPathTile(AlphaPaintPipe.java:106) 
    at sun.java2d.pipe.DuctusShapeRenderer.renderTiles(DuctusShapeRenderer.java:147) 
    at sun.java2d.pipe.DuctusShapeRenderer.renderPath(DuctusShapeRenderer.java:100) 
    at sun.java2d.pipe.DuctusShapeRenderer.fill(DuctusShapeRenderer.java:50) 
    at sun.java2d.pipe.PixelToParallelogramConverter.fill(PixelToParallelogramConverter.java:146) 
    at sun.java2d.pipe.ValidatePipe.fill(ValidatePipe.java:142) 
    at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2376) 
    at sun.print.ProxyGraphics2D.fill(ProxyGraphics2D.java:1381) 
    at com.sun.pdfview.pattern.PatternType1$TilingPatternPaint.fill(PatternType1.java:278) 
    at com.sun.pdfview.PDFRenderer.fill(PDFRenderer.java:261) 
    at com.sun.pdfview.PDFShapeCmd.execute(PDFShapeCmd.java:77) 
    at com.sun.pdfview.PDFRenderer.iterate(PDFRenderer.java:570) 
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:101) 
    at **MYFILEHERE** 

這在一個文件中,只有一半的打印,停止甚至跨越文本行的中心導致文件中途失敗,結果硬是(和有些幽默)。

這個錯誤的原因是什麼?它在渲染過程中處於如此低級別,處理個人形狀操作,我不得不相信它是我無法控制的。 有沒有辦法,我可以讓我的過程繞過損壞的數據,它可能正在努力並繼續呈現文件完整?

+0

什麼這裏發生了什麼? 'PatternType1.java:278'和'PDFRenderer.java:261' – Brian

+0

獲取更多數據的建議:在您的代碼中捕獲異常。從catch塊中,將緩衝區的內容轉儲到磁盤文件,然後在pdf閱讀程序中打開它。另外,你確定你總是閱讀整個輸入文件嗎? –

+0

@布萊恩我不認爲我可以知道。這是com.sun代碼。 –

回答

1

事實證明,這是正在執行的代碼是不是Sun的Java的官方代碼部分,由包的com.sun名稱作爲建議,而是一個單獨的項目位於here。代碼是開放源代碼,允許我檢查出來,修改this文件,並構建自己的一個新的jar很容易。如果可能的話,我也會嘗試爲我的項目提供修補。

該修復只是添加一個檢查,以防止前面提到的Divide-by-Zero錯誤。

原始代碼:

xloc %= useXStep; 
yloc %= useYStep; 

固定碼:

if (xstep != 0) 
    xloc %= useXStep; 
if (ystep != 0) 
    yloc %= useYStep;