生成大型pdf,而主存储器中没有内容

时间:2019-04-10 03:28:41

标签: java pdf itext pdf-generation

我正在使用iText生成pdf格式的超大表格。 生成这些表而不是将全部内容存储在内存中的最佳方法是什么? 如果我只是将for循环中的以下大小增加到一百万,我用完了内存,是否有比将全部内容都存储在内存中更好的流传输方法

我看到了这篇帖子How to directly stream large content to PDF with minimal memory footprint? 但是我想知道要使用什么iText api。

示例代码:

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class SimpleTable11 {
public final static String DEST = "/Users/.../Documents/test23.pdf";

public static void main(String[] args) throws IOException, DocumentException {
    new SimpleTable11().createPdf(DEST);
}

public void createPdf(String dest) throws IOException, DocumentException {

    System.out.println(new Date());
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream(DEST));
    document.open();
    PdfPTable table = new PdfPTable(23);
    table.setWidths(new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
    table.setWidthPercentage(100);
    table.addCell(createCell("Account", 2, 1, Element.ALIGN_JUSTIFIED));
    table.addCell(createCell("Org Id", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Contract Number", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Transaction Type", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Transaction Number", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Transaction Date", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Start Date", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("End Date", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Billing Reference", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Line Description", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Product Name", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Related Invoices", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Monthly Unit Price", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("quantity", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Total Line Tax", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Total Price", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Exchange Rate", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Taxable", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Vat Rate", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("VAT", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Taxable", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("VAT", 2, 1, Element.ALIGN_LEFT));
    table.addCell(createCell("Total Price", 2, 1, Element.ALIGN_LEFT));

    String[] data = { "44445555", "123456", "0105567", "INV", "123456", "10/10/2018", "11/15/2018", "11/20/2050",
            "SO-0000000000-Mento", "Marketing Product", "Marketing Product ", "Marketing Product",
            "Marketing Product", "0.00", "12.56", "300.00", "0.566667345", "12.54", "10.00%", "12.56", "7.58",
            "7.27", "176.67" };
    for (int i = 0; i < 20000; i++) {
        for (int j = 0; j < data.length; j++) {
            table.addCell(createCell(data[j], 1, 1, Element.ALIGN_LEFT));
        }
    }
    document.add(table);
    document.close();
    System.out.println(new Date());
}

public PdfPCell createCell(String content, float borderWidth, int colspan, int alignment) {
    Font font = new Font(FontFamily.HELVETICA, 4, Font.NORMAL);
    PdfPCell cell = new PdfPCell(new Phrase(content, font));
    cell.setBorderWidth(borderWidth);
    cell.setColspan(colspan);
    cell.setHorizontalAlignment(alignment);
    return cell;
}

}

1 个答案:

答案 0 :(得分:1)

在将PdfPTable对象用于许多单元格时,应使用实现LargeElement的类,该类记录为

/**
 * Interface implemented by Element objects that can potentially consume
 * a lot of memory. Objects implementing the LargeElement interface can
 * be added to a Document more than once. If you have invoked setComplete(false),
 * they will be added partially and the content that was added will be
 * removed until you've invoked setComplete(true);
 * @since   iText 2.0.8
 */
public interface LargeElement extends Element

即您应该先使用

setComplete(false),

然后将一些内容(例如20行)添加到表中,然后将表添加到文档中,添加更多内容,再次将表添加到文档中,依此类推...,等添加所有内容后,使用< / p>

setComplete(true)

,然后再次添加表格。这样,表数据就不会保留在堆中,而是一点一点地序列化并写入写程序。


顺便说一句,还有其他iText类也实现了LargeElement。如果iText占用大量内存,则应始终检查添加到Document的对象:如果它们实现了LargeElement,请首先尝试将它们转发到Document如上所解释。