Ajuda com StringTokenizer

13 respostas
robinsonbsilva

Senhores(as), preciso de uma ajuda para compreender o que está ocorrendo para a seguintes linhas contida num .txt. Eu lerei essas informações e as inserirei em um banco de dados. Cada coluna é separada por “;” e mesmo as que não tem informação devem ser populadas no bean. O problema ocorre quando tenho uma coluna vazia, apenas com o valor “;” …o token não conta tal coluna, abaixo tenho 14 colunas, mas ao rodar só reconhece 7 tokens…

ARQUIVO TXT

903;DÉBITOS;[telefone removido];;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE  10;
903;DÉBITOS;20623;;08/01/2009;1;          ;;;;;-10;-10;Tx. Adesão,AMIL SAÚDE,RENATA ALMEIDA ;

ROTINA LEITURA

private void processFile(HttpServletRequest request) throws BDOException {

		try {
			
			String transacao = getBufferFile().readLine();
			while (transacao != null) {

				StringTokenizer colunas = new StringTokenizer(transacao, ";");

				while (colunas.hasMoreTokens()) {

					int idVendedor = Integer.parseInt(colunas.nextToken().trim());
					String operadora = colunas.nextToken().trim();
					String numeroProposta = colunas.nextToken().trim();
					String cliente = colunas.nextToken().trim();
					String idLote = colunas.nextToken().trim();
					String dataAdesao = colunas.nextToken().trim();
					String parcela = colunas.nextToken().trim();
					String dataPagto = colunas.nextToken().trim();
					String valorPago = colunas.nextToken().trim();
					String porcComissao = colunas.nextToken().trim();
					String valorComissao = colunas.nextToken().trim();
					String porcDesconto = colunas.nextToken().trim();
					String valorDesconto = colunas.nextToken().trim();
					String valorLiquido = colunas.nextToken().trim();

					ProcessImport dto = new ProcessImport();
					dto.setIdVendedor(idVendedor);
					dto.setIdLote(idLote);
					dto.setOperadora(operadora);
					dto.setCliente(cliente);
					dto.setNumeroProposta(numeroProposta);
					dto.setCliente(cliente);
					dto.setDataAdesao(dataAdesao);
					dto.setParcela(parcela);
					dto.setDataPagto(dataPagto);
					dto.setValorPago(valorPago);
					dto.setPorcComissao(porcComissao);
					dto.setValorComissao(valorComissao);
					dto.setPorcDesconto(porcDesconto);
					dto.setValorDesconto(valorDesconto);
					dto.setValorLiquido(valorLiquido);

					FactoryDAO.getProcessImport(request).insert(dto);
					transacao = bufferFile.readLine();
					dto = null;
				}
			}
		} catch (IOException e) {
			throw new BDOException("Erro ao processar o arquivo.");
		} catch (DAOException e) {
			throw new BDOException("Erro ao inserir os registros.");
		}
	}

13 Respostas

M

Uma alternativa seria trocar os caracteres ;; por ; ;

Seria assim:

String transacao = "903;DÉBITOS;20623;;08/01/2009;1; ;;;;;-10;-10;Tx. Adesão,AMIL SAÚDE,RENATA ALMEIDA ; ";

transacao =transacao.replace(";;", "; ;");
	System.out.println(transacao);
	StringTokenizer colunas = new StringTokenizer(transacao, ";");   
	System.out.println(colunas.countTokens());
	while (colunas.hasMoreTokens()) {  
		System.out.println(colunas.nextToken().trim());
	}
robinsonbsilva

Bom meneghette !!
Então, ja testei dessa forma, e não funciona.

Alguma :idea:.

Obrigado!

M

robinson,

Testei da forma que te passei e deu certo… veja o resultado:

Qtde Colunas = 13
903
DÉBITOS
20623

08/01/2009
1

-10
-10
Tx. Adesão,AMIL SAÚDE,RENATA ALMEIDA

robinsonbsilva

Estranho é que ele está ignorando uma coluna ainda.
O seguinte layout foi utilizado para o arquivo:

Coluna 1 - Cód. Vendedor
Coluna 2 - Operadora
Coluna 3 - Nro. Proposta
Coluna 4 - Cliente
Coluna 5 - Lote
Coluna 6 - Data Adesão
Coluna 7 - Parcela
Coluna 8 - Data Pagto
Coluna 9 - Valor Pago
Coluna 10 - % Comissão
Coluna 11 - Valor Comisão
Coluna 12 - % Desconto
Coluna 13 - Valor Desconto
Coluna 14 - Valor Líquido
M

É verdade, você tem razão, pois quando fez o repalce.. restaram alguns ;; juntos, assim ele não encontrou todas as colunas...

fiz a seguinte alteração e agora deu:

public static void main(String[] args) {

		String transacao = "903;DÉBITOS;20623;;08/01/2009;1; ;;;;;-10;-10;Tx. Adesão,AMIL SAÚDE,RENATA ALMEIDA ; "; 

[b]		while (transacao.contains(";;"))
			transacao =transacao.replace(";;", "; ;");[/b]
		
		System.out.println(transacao); 
		StringTokenizer colunas = new StringTokenizer(transacao, ";"); 
		System.out.println(colunas.countTokens()); 
		while (colunas.hasMoreTokens()) { 
		System.out.println(colunas.nextToken().trim()); 
		}

	}
robinsonbsilva

Consegui resolver esse problema sem ter que recorrer a “gambiarras.rs” 8)
Veja a solução abaixo:

String linha = "903;DÉBITOS;[telefone removido];;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE Nº 10;"; //teste
    String colunas[] = linha.split("\;");
    for(String coluna : colunas){
        System.out.println(coluna);			
    }

VALEU PELA FORÇA meneghette !!!

M

Show de bola

Djonatah

robinson silva,

Quando for tokenizar alguma coisa, use a classe Scanner. Acredito que ela seja o Cadilac da tokenizacao.

Abracos.
<><

T
robinsonbsilva:
Senhores(as), preciso de uma ajuda para compreender o que está ocorrendo para a seguintes linhas contida num .txt. Eu lerei essas informações e as inserirei em um banco de dados. Cada coluna é separada por ";" e mesmo as que não tem informação devem ser populadas no bean. O problema ocorre quando tenho uma coluna vazia, apenas com o valor ";" ..o token não conta tal coluna, abaixo tenho 14 colunas, mas ao rodar só reconhece 7 tokens.. ARQUIVO TXT
903;DÉBITOS;[telefone removido];;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE  10;
903;DÉBITOS;20623;;08/01/2009;1;          ;;;;;-10;-10;Tx. Adesão,AMIL SAÚDE,RENATA ALMEIDA ;
ROTINA LEITURA
private void processFile(HttpServletRequest request) throws BDOException {

		try {
			
			String transacao = getBufferFile().readLine();
			while (transacao != null) {

				StringTokenizer colunas = new StringTokenizer(transacao, ";");

				while (colunas.hasMoreTokens()) {

					int idVendedor = Integer.parseInt(colunas.nextToken().trim());
					String operadora = colunas.nextToken().trim();
					String numeroProposta = colunas.nextToken().trim();
					String cliente = colunas.nextToken().trim();
					String idLote = colunas.nextToken().trim();
					String dataAdesao = colunas.nextToken().trim();
					String parcela = colunas.nextToken().trim();
					String dataPagto = colunas.nextToken().trim();
					String valorPago = colunas.nextToken().trim();
					String porcComissao = colunas.nextToken().trim();
					String valorComissao = colunas.nextToken().trim();
					String porcDesconto = colunas.nextToken().trim();
					String valorDesconto = colunas.nextToken().trim();
					String valorLiquido = colunas.nextToken().trim();

					ProcessImport dto = new ProcessImport();
					dto.setIdVendedor(idVendedor);
					dto.setIdLote(idLote);
					dto.setOperadora(operadora);
					dto.setCliente(cliente);
					dto.setNumeroProposta(numeroProposta);
					dto.setCliente(cliente);
					dto.setDataAdesao(dataAdesao);
					dto.setParcela(parcela);
					dto.setDataPagto(dataPagto);
					dto.setValorPago(valorPago);
					dto.setPorcComissao(porcComissao);
					dto.setValorComissao(valorComissao);
					dto.setPorcDesconto(porcDesconto);
					dto.setValorDesconto(valorDesconto);
					dto.setValorLiquido(valorLiquido);

					FactoryDAO.getProcessImport(request).insert(dto);
					transacao = bufferFile.readLine();
					dto = null;
				}
			}
		} catch (IOException e) {
			throw new BDOException("Erro ao processar o arquivo.");
		} catch (DAOException e) {
			throw new BDOException("Erro ao inserir os registros.");
		}
	}

Não use StringTokenizer de forma alguma para separar campos se houver campos vazios.
Não use, não use e não use; ponto final.
Olhe o fonte de StringTokenizer se tiver alguma dúvida.
Se precisar separar campos vazios, use String.split, que é o que você deveria ter usado desde o começo.
E mais uma coisa: use a versão com 2 parâmetros de String.split. É que a versão com 1 parâmetro não retorna os campos vazios no final da string; a com 2 parâmetros (sendo o 2o. parâmetro = -1) consegue retornar os campos vazios.

robinsonbsilva

Valeu thingol pelos esclarecimentos!!!

Como funcionaria esse:

public String[] split(String regex,int limit)

Pois eu usei a versão com um parâmetro

String linha = "903;DÉBITOS;[telefone removido];;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE Nº 10;"; //teste   
    String colunas[] = linha.split("\;");   
    for(String coluna : colunas){   
        System.out.println(coluna);           
    }
T

limit (o segundo parâmetro) indica qual é o tamanho máximo do array que String.split deve retornar, se for positivo. Por exemplo, String s = "a;b;c;d;e;f;g;h;;;"; String[] t = s.split (";", 5);
iria retornar um array t de 5 elementos com o conteúdo “a”, “b”, “c”, “d”, “e;f;g;h;;;”.

Se você passar -1, então ele não tem limite nenhum, e também volta os campos vazios no final da string caso existirem. Por exemplo,

String s = "a;b;c;d;e;f;g;h;;;";
String[] t = s.split (";", -1);

iria retornar um array t com o conteúdo “a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “”, “”, “”. (Tomei pau em contabilidade e não sei contar ou fazer contas, por favor conte quantos elementos teria o array.)

robinsonbsilva

Perfeito!

Obrigadão pela “aula”!

O

robinson, repare no código do thingol que a barra dupla que você colocou como argumento para o split é desnecessária.
flw.

Criado 11 de fevereiro de 2009
Ultima resposta 11 de fev. de 2009
Respostas 13
Participantes 5