Manipulacao de XML com JAXB extremamente lenta

5 respostas Resolvido
xmlprogramaçãojava
T

Ola,
Eu fiz um codigo bem simples. Um esboço do que eu quero fazer. Porem está extremamente lento. Eu quero abrir um arquivo XML de uma nota fiscal eletronica (NFC-e), e pegar o falor do pagamento. O processo esta funcionando. Porem eu quero fazer isso usando todas as notas emitidas num mes. Estou fazendo um teste com 2200 arquivos. Esta levando mais de meia hora para concluir. O codigo é bem simples, esta logo abaixo, alguem usa alguma outra biblioteca para fazer isso?

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
	File diretorio = selecionarArquivo(true);
	if (diretorio == null) {
		JOptionPane.showMessageDialog(this, "Arquivo nao selecionado ou nao encontrado.", "Erro ao selecionar arquivo", JOptionPane.ERROR_MESSAGE);
	} else {
		StringBuffer sb = new StringBuffer();
		File[] arquivos = diretorio.listFiles();
		for (File arquivo : arquivos) {
			if (!arquivo.getName().contains("caneve")) {
				try {
                    //daqui
					JAXBContext contexto = JAXBContext.newInstance("br.inf.portalfiscal.nfe");
					Unmarshaller leituraXML = contexto.createUnmarshaller();
					JAXBElement<TNfeProc> objetoXML = (JAXBElement<TNfeProc>) leituraXML.unmarshal(arquivo);
					TNfeProc nfe = objetoXML.getValue();
                    //ate aqui, leva de 2 a 3 segundos por arquivo é o gargalo.
					sb.append(nfe.getNFe().getInfNFe().getId().substring(3));
					sb.append("\tEMISSAO:\t");
					sb.append(LocalDate.parse(nfe.getNFe().getInfNFe().getIde().getDhEmi(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));
					sb.append("\r\n");
					for (TNFe.InfNFe.Pag.DetPag pag : nfe.getNFe().getInfNFe().getPag().getDetPag()) {
						sb.append("PAGAMENDO:\t");
						sb.append(pag.getTPag());
						sb.append("\tVALOR:\t");
						sb.append(pag.getVPag());
						sb.append("\r\n");
					}					
				} catch (JAXBException ex) {
					ex.printStackTrace();
				} 
			}
		}
		System.out.println(sb);
	}
}

5 Respostas

L
Solucao aceita

Será que vc não pode reutilizar essas duas linhas? Talvez o contexto e o unmarshaller possa ser o mesmo para todos os arquivos. (obs.: Nunca precisei usar o jaxb, pensei nisso por dedução mesmo, talvez nem funcione)

B

JAXBContext contexto = JAXBContext.newInstance(“br.inf.portalfiscal.nfe”);

vc ta criando uma instancia de um pacote de classes a cada iteração do loop de arquivo. Tente passar apenas a classe desse Jaxb. a dica que o @ lucastody tbm não é desperdiçada…

T

eu ia excluir o topico, mas pode ser que sirva para outra pessoa.

JAXBContext contexto = JAXBContext.newInstance("br.inf.portalfiscal.nfe");

essa criacao de uma instancoa do JAXBContext deve ser invocada uma unica vez e caso necessario voce compartilha ela entre os objetos. O meu erro foi ficar criando varias vezes dentro do for.
Nesse caso bastou retirar do for sua criacao, juntamente com a do Unmarshaller. Que agora nao leva mais nem 1 segundo a mesma tarefa.

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
	File diretorio = selecionarArquivoDaColeta(true);
	if (diretorio == null) {
		JOptionPane.showMessageDialog(this, "Arquivo nao selecionado ou nao encontrado.", "Erro ao selecionar arquivo", JOptionPane.ERROR_MESSAGE);
	} else {
		long t1 = System.currentTimeMillis();
		StringBuffer sb = new StringBuffer();
		File[] arquivos = diretorio.listFiles();
		try {
			//Retirei a criacao desses dois objetos do for. 
			JAXBContext contexto = JAXBContext.newInstance("br.inf.portalfiscal.nfe");
			Unmarshaller leituraXML = contexto.createUnmarshaller();
			for (File arquivo : arquivos) {
				if (!arquivo.getName().contains("caneve")) {
					JAXBElement<TNfeProc> objetoXML = (JAXBElement<TNfeProc>) leituraXML.unmarshal(arquivo);
					TNfeProc nfe = objetoXML.getValue();
					sb.append(nfe.getNFe().getInfNFe().getId().substring(3));
					sb.append("\tEMISSAO:\t");
					sb.append(LocalDate.parse(nfe.getNFe().getInfNFe().getIde().getDhEmi(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));
					sb.append("\r\n");
					for (TNFe.InfNFe.Pag.DetPag pag : nfe.getNFe().getInfNFe().getPag().getDetPag()) {
						sb.append("PAGAMENDO:\t");
						sb.append(pag.getTPag());
						sb.append("\tVALOR:\t");
						sb.append(pag.getVPag());
						sb.append("\r\n");
					}
				}
			}
		} catch (JAXBException ex) {
			ex.printStackTrace();
		}
		System.out.println(sb);
	}
}
T

blz, eu fui dar uma googada, e achei essa sua dica. valeu ae.

T

valeu obrigado, foi justamente isso

Criado 28 de abril de 2020
Ultima resposta 28 de abr. de 2020
Respostas 5
Participantes 3