Ajuda com StringTokenizer

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;0000000000;;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE Nº 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.");
		}
	}

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());
	}

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

Alguma :idea:.

Obrigado!

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

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

É 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:

[code]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 ; "; 

while (transacao.contains(";;"))
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()); 
	}

}[/code]

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

String linha = "903;DÉBITOS;0000000000;;;;          ;;;;;-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 !!!

Show de bola

robinson silva,

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

Abracos.
<><

[quote=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;0000000000;;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE Nº 10;
903;DÉBITOS;20623;;08/01/2009;1;          ;;;;;-10;-10;Tx. Adesão,AMIL SAÚDE,RENATA ALMEIDA ;

ROTINA LEITURA

[code]
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.");
	}
}

[/code][/quote]

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.

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;0000000000;;;;          ;;;;;-30;-30;SALDO DEVEDOR REF. LOTE Nº 10;"; //teste   
    String colunas[] = linha.split("\;");   
    for(String coluna : colunas){   
        System.out.println(coluna);           
    }

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.)

Perfeito!

Obrigadão pela “aula”!

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