Olá, embora este seja meu primeiro post aki, já consulto este fórum há algum tempo. Sou bastante novato em java e não tenho alguém experiente para perguntar, então é aqui que me refugio para sanar minhas dúvidas e tento ser muito persistente até achar o que quero. Acontece que agora estou com um problema do qual não estou conseguindo encontrar a melhor solução. É meu primeiro aplicativo java oficial e preciso gerar um pdf com o resultado de um log de impressão previamente lido e exibido na tela. Ele funciona muito bem até uma certa quantidade de resultados, mas a partir de um certo ponto ele da o erro “java.lang.OutOfMemoryError”. Consegui tranquilamente criar um pdf com umas 700 páginas, mas acima disto começa a dar o erro. Sei que alguns podem me questionar sobre o porque de um pdf tão grande, e já adianto que realmente dificilmente precisarei de mais do que isto, acontece que o além de existir uma possibilidade, embora muito remota, tem uma outra questão, por ser novato sei que meu código pode melhorar e além disto será um bom aprendizado com o I/O pois sei que se mal escrito, pode comprometer muito uma aplicação. Eu sei que a melhor forma é jogar para um BufferOutputStream e assim o fiz de uma maneira simples mas que não resolveu o problema, acredito que porque embora com o buffer, na hora de gravar, continua tentando gravar tudo de uma vez. Gostaria de saber como poderia fazer para ir gravando aos poucos, tipo, estipular um tamanho para o buffer e quando ele estivesse com aquele tamanho, ir jogando para o arquivo, e quando terminasse, fecho o arquivo. Saber como trabalhar isto seria de grande valia, não só para este, como para outros aplicativos futuros.
Segue o código:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
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.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import model.Log;
public class GerarPDFLogImpressoes {
private PdfPTable tabela;
private PdfPCell celula;
private Font fonteCabecalho;
private Font fonteDados;
PdfWriter writer = null;
private BufferedOutputStream bos;
private FileOutputStream os;
private Document documento;
public GerarPDFLogImpressoes(ArrayList<Log> logs, String qtdeImpressoes) {
try {
// Cria uma nova instancia PdfWriter com os paramentos do documento
// e do buffer de saida
writer = PdfWriter.getInstance(getDocumento(), getBos());
// Abre o documento para edicao
getDocumento().open();
// Adicionar a linha do cabecalho
definirCabecalho();
// Faz uma varredura do array de logs e vai adicionando a tabela
for (Log log : logs) {
getTabela().addCell(getCelula(new SimpleDateFormat("dd/MM/yyyy HH:mm").format(log.getTime()), Element.ALIGN_CENTER, getFonteDados()));
getTabela().addCell(getCelula(log.getUser(), Element.ALIGN_CENTER, getFonteDados()));
getTabela().addCell(getCelula(log.getClient(), Element.ALIGN_CENTER, getFonteDados()));
getTabela().addCell(getCelula(log.getDocumentName(), Element.ALIGN_LEFT, getFonteDados()));
getTabela().addCell(
getCelula(NumberFormat.getInstance().format(((long) log.getPages() * (long) log.getCopies())), Element.ALIGN_CENTER, getFonteDados()));
getTabela().addCell(getCelula(log.getPrinter(), Element.ALIGN_CENTER, getFonteDados()));
getTabela().addCell(getCelula(log.getPaperSize(), Element.ALIGN_CENTER, getFonteDados()));
getTabela().addCell(getCelula(log.getGrayscale(), Element.ALIGN_CENTER, getFonteDados()));
}
// Adiciona o rodape ao final da tabela
definirRodape(qtdeImpressoes);
// Adiciona a tabela criada ao documento aberto
getDocumento().add(getTabela());
// Trata os erros
} catch (DocumentException e) {
System.out.println(e.getMessage());
// Finaliza o arquivo
} finally {
// Finaliza o documento
if (getDocumento() != null) {
getDocumento().close();
}
// Finaliza o buffer
if (getBos() != null) {
try {
getBos().close();
// Abre o arquivo recem criado
java.awt.Desktop.getDesktop().open(new File("Relatório de impressão.pdf"));
// Trata os erros
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
private BufferedOutputStream getBos() {
if (bos == null) {
bos = new BufferedOutputStream(getOs());
}
return bos;
}
private FileOutputStream getOs() {
if (os == null) {
try {
os = new FileOutputStream("Relatório de impressão.pdf");
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
}
return os;
}
// Trata o documento
private Document getDocumento() {
if (documento == null) {
documento = new Document(PageSize.A4.rotate(), 20, 20, 20, 20);
}
return documento;
}
// Trata a fonte do cabecalho
private Font getFonteCabecalho() {
if (fonteCabecalho == null) {
fonteCabecalho = new Font(FontFamily.HELVETICA, 11, Font.BOLD);
}
return fonteCabecalho;
}
// Trata a fonte do rodape
private Font getFonteRodape() {
if (fonteCabecalho == null) {
fonteCabecalho = new Font(FontFamily.HELVETICA, 10, Font.BOLD);
}
return fonteCabecalho;
}
// Trata a fonte dos dados
private Font getFonteDados() {
if (fonteDados == null) {
fonteDados = new Font(FontFamily.HELVETICA, 9);
}
return fonteDados;
}
// Adiciona a linha do cabecalho
private void definirCabecalho() {
getTabela().addCell(getCelula("Data / Hora", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Usuário", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Computador", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Nome do documento", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Impressões", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Impressora", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Papel", Element.ALIGN_CENTER, getFonteCabecalho()));
getTabela().addCell(getCelula("Cor", Element.ALIGN_CENTER, getFonteCabecalho()));
}
// Adiciona a linha do rodape
private void definirRodape(String qtdeImpressoes) {
PdfPCell celulaRodape = getCelula("Total de impressões: " + qtdeImpressoes, Element.ALIGN_RIGHT, getFonteRodape());
celulaRodape.setColspan(9);
celulaRodape.setBorder(PdfPCell.NO_BORDER);
getTabela().addCell(celulaRodape);
}
// Trata a tabela
private PdfPTable getTabela() {
if (tabela == null) {
tabela = new PdfPTable(new float[] { 0.100f, 0.125f, 0.125f, 0.350f, 0.100f, 0.120f, 0.045f, 0.035f });
tabela.setWidthPercentage(100f);
}
return tabela;
}
// Trata a celula
private PdfPCell getCelula(String texto, int alinhamento, Font fonte) {
celula = new PdfPCell(new Phrase(texto, fonte));
celula.setMinimumHeight(15f);
celula.setHorizontalAlignment(alinhamento);
celula.setVerticalAlignment(Element.ALIGN_MIDDLE);
return celula;
}
}