2017-02-16 64 views
0

我正在合并多个文件,最初有19mb。pdfbox写压缩对象流

但结果总共56mb。我怎样才能使这个最终价值接近19mb。 [编辑]

public void concatena(InputStream anterior, InputStream novo, OutputStream saida, List<String> marcadores) 
    throws IOException { 
    PDFMergerUtility pdfMerger = new PDFMergerUtility(); 
    pdfMerger.setDestinationStream(saida); 
    PDDocument dest; 
    PDDocument src; 
    MemoryUsageSetting setupMainMemoryOnly = MemoryUsageSetting.setupMainMemoryOnly(); 
    if (anterior != null) {      
     dest = PDDocument.load(anterior, setupMainMemoryOnly); 
     src = PDDocument.load(novo, setupMainMemoryOnly); 
    } else { 
     dest = PDDocument.load(novo, setupMainMemoryOnly); 
     src = new PDDocument(); 
    }  
    int totalPages = dest.getNumberOfPages(); 
    pdfMerger.appendDocument(dest, src); 
    criaMarcador(dest, totalPages, marcadores); 
    saida = pdfMerger.getDestinationStream(); 
    dest.save(saida); 
    dest.close(); 
    src.close(); 
} 

对不起,我还是不知道如何使用计算器非常好。我试图张贴代码的其余部分,但我得到一个错误

[编辑2 - 增加criaMarcador方法]

private void criaMarcador(PDDocument src, int numPaginas, List<String> marcadores) { 
    if (marcadores != null && !marcadores.isEmpty()) { 
     PDDocumentOutline documentOutline = src.getDocumentCatalog().getDocumentOutline();   
     if (documentOutline == null) { 
      documentOutline = new PDDocumentOutline(); 
     } 
     PDPage page; 
     if (src.getNumberOfPages() == numPaginas) { 
      page = src.getPage(0); 
     } else { 
      page = src.getPage(numPaginas); 
     } 
     PDOutlineItem bookmark = null; 
     PDOutlineItem pai = null; 
     String etiquetaAnterior = null; 
     for (String etiqueta : marcadores) {     
      bookmark = bookmark(pai != null ? pai : documentOutline, etiqueta); 
      if (bookmark == null) { 
       if (etiquetaAnterior != null && !etiquetaAnterior.equals(etiqueta) && pai == null) { 
        pai = bookmark(documentOutline, etiquetaAnterior); 
       } 
       bookmark = new PDOutlineItem(); 
       bookmark.setTitle(etiqueta); 
       if (marcadores.indexOf(etiqueta) == marcadores.size() - 1) { 
        bookmark.setDestination(page); 
       } 
       if (pai != null) { 
        pai.addLast(bookmark); 
        pai.openNode(); 
       } else { 
        documentOutline.addLast(bookmark); 
       } 
      } else { 
       pai = bookmark; 
      } 
      etiquetaAnterior = etiqueta; 
     } 
     src.getDocumentCatalog().setDocumentOutline(documentOutline);   
    }  
} 

private PDOutlineItem bookmark(PDOutlineNode outline, String etiqueta) {    
    PDOutlineItem current = outline.getFirstChild(); 
    while (current != null) { 
     if (current.getTitle().equals(etiqueta)) { 
      return current; 
     } 
     bookmark(current, etiqueta); 
     current = current.getNextSibling(); 
    } 
    return current; 
} 

[编辑3]下面是用于测试

代码
public class PDFMergeTeste { 


public static void main(String[] args) throws IOException { 
    if (args.length == 1) { 
     PDFMergeTeste teste = new PDFMergeTeste(); 
     teste.executa(args[0]); 
    } else { 
     System.err.println("Argumento tem que ser diretorio contendo arquivos .pdf com nomeclatura no padrão Autos"); 
    } 
} 

private void executa(String diretorioArquivos) throws IOException { 
    File[] listFiles = new File(diretorioArquivos).listFiles((pathname) -> 
      pathname.getName().endsWith(".pdf") || pathname.getName().endsWith(".PDF")); 
    List<File> lista = Arrays.asList(listFiles); 
    lista.sort(Comparator.comparing(File::lastModified)); 
    PDFMerge merge = new PDFMerge(); 
    InputStream anterior = null; 
    ByteArrayOutputStream saida = new ByteArrayOutputStream(); 
    for (File file : lista) { 
     List<String> marcadores = marcadores(file.getName());   
     InputStream novo = new FileInputStream(file);   
     merge.concatena(anterior, novo, saida, marcadores);      
     anterior = new ByteArrayInputStream(saida.toByteArray()); 
    } 
    try (OutputStream pdf = new FileOutputStream(pathDestFile)) { 
     saida.writeTo(pdf); 
    } 


} 
private List<String> marcadores(String name) { 
    String semExtensao = name.substring(0, name.indexOf(".pdf")); 
    return Arrays.asList(semExtensao.split("_"));  
} 

}

+0

请分享文件。并告诉你的版本。 –

+0

@TilmanHausherr https://www.dropbox.com/sh/elbjegfykxux6wf/AAC8SMU6-7_sAPS7yqgZkDn0a?dl=0 –

+0

@ArthurMenezes这些文件是你必须合并的文件的样本? – mkl

回答

1

的错误是在executa方法:

InputStream anterior = null; 
ByteArrayOutputStream saida = new ByteArrayOutputStream(); 
for (File file : lista) { 
    List<String> marcadores = marcadores(file.getName());   
    InputStream novo = new FileInputStream(file);   
    merge.concatena(anterior, novo, saida, marcadores);      
    anterior = new ByteArrayInputStream(saida.toByteArray()); 
} 

您的ByteArrayOutputStream saida在每个循环中都被重复使用,但不会被清除。因此,它包含

  • 处理文件1后:
    • 文件1
    • 级联文件1和文件2的:处理文件2之后
      • 文件1
  • 处理文件3之后:文件1
    • 文件1
    • 文件1和文件2
    • 级联文件1和文件2和处理文件4之后文件3
  • 的级联:
    • 文件1
    • 文件1和文件2级联
    • 级联文件1和文件2和文件3
    • 级联文件1和文件2和文件3和文件4

(其实这只能是因为PDFBox的尝试是好的和修复由于这些严格地说文件连接被破坏,并且PDFBox不需要能够解析它们,所以在引擎盖下破坏了输入文件。)

您可以通过在每个迭代开始清理saida解决这个问题:

InputStream anterior = null; 
ByteArrayOutputStream saida = new ByteArrayOutputStream(); 
for (File file : lista) { 
    saida.reset(); 
    List<String> marcadores = marcadores(file.getName());   
    InputStream novo = new FileInputStream(file);   
    merge.concatena(anterior, novo, saida, marcadores);      
    anterior = new ByteArrayInputStream(saida.toByteArray()); 
} 

与您原来的方法为您输入的结果的大小几乎是26 MB,与固定方法,有大约5 MB ,后者大小近似表示输入文件大小的总和。

+0

它的工作!感谢您的帮助。 –