Lendo arquivo text com StringTokenizer

Pessoal estou lendo um arquivo texto com StringTokenizer com o seguinte formato:

NumeroOS;DataAbertura;TamanhoPF;PercentualErros;DataEntrega;Obs

OS102086 ; 2010-03-15 ; 0 ; 0 ; 2010-03-18 ; Este é um teste de arquivo;favor não quevra lalalalal

O que eu quero fazer é quando chegar na Observação ele pegue todo o elemento mesmo se ouver um ( ; ) ponto e virgula pois ela pode conter esse tipo de caracter… não quero trocar o tipo de delimitador por isso preciso de um ajudinha.

segue codigo:

 public void listener(UploadEvent event) throws Exception {
        SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        UploadItem arquivo = event.getUploadItem();

        try {
            BufferedReader reader = new BufferedReader(new FileReader(arquivo.getFile()));
            String dados[] = new String[7];
            String linha = reader.readLine();

            while (linha != null) {                
                StringTokenizer st = new StringTokenizer(linha, ";");
                dados[0] = st.nextToken();
                dados[1] = st.nextToken();
                dados[2] = st.nextToken();
                dados[3] = st.nextToken();
                dados[4] = st.nextToken();
                dados[5] = st.nextToken();

                String numeroOS = dados[0];
                Date dataAbertura = (Date) df.parse(dados[1]);
                float tamanhoPF = Float.parseFloat(dados[2]);
                float percentualErros = Float.parseFloat(dados[3]);
                Date dataEntrega = (Date) df.parse(dados[4]);
                String obs = dados[5];
                
                //Cria um Objeto OS
                Os os = new Os();
                os.setNumero_os(numeroOS);
                os.setNum_asc(getAscSelecionada());
                os.setData_abertura_os(dataAbertura);
                os.setTamanho_pf_os(tamanhoPF);
                os.setPerc_erros_os(percentualErros);
                os.setObs_os(obs);
                os.setStatus_os(1); //sempre será 1 - Aberto
                os.setDataEntrega_os(dataEntrega);

                //Inseri no Banco de Dados
                OsControle controle = new OsControle();
                controle.inserirImportacao(os);

                linha = reader.readLine();
            }

            reader.close();

        } catch (Exception excecao) {
            //logger.error("Erro ao tentar efetuar o upload de arquivo", excecao);
        }
    }

Eu faria:
2 StringTokenizer
1 separando por linhas
O outro, um array de ST, separando por ;
Dae eu pegaria os primeiros tokens, e se a obs for o 5º token, iria concatenando se houvessem mais tokens, tipo str += nextToken() + “;”;
sak?

oba ideia… value!!

Tio, não use StringTokenizer. É que ele não funciona direito para campos vazios.

Use String.split, com 2 parâmetros; o segundo parâmetro diz qual é a quantidade máxima de campos.

desculpa … não entendi ?? como você faria neste caso?

pelo StringTokenizer ele está pegando corretamente os espaços o problema está no campo Obs não sei como fazer para concatenar para a observação caso tenha ( ; ) ponto e virgula.

funciono a ideia a cima… fiz mais simple acho!

so acresentei e depois setei o valor.

dadosObs = st.nextToken();
while(st.hasMoreTokens()){
dadosObs = dadosObs + st.nextToken();
}


String txt = "OS102086 ; 2010-03-15 ; 0 ; 0 ; 2010-03-18 ; Este é um teste de arquivo;favor não quevra lalalalal"
String[] quebrada = txt.split(";", 5);

Resultado:

quebrada[0]="OS102086"
quebrada[1]="2010-03-15" 
quebrada[2]="0"
quebrada[3]="0"
quebrada[4]="2010-03-18"
quebrada[5]="Este é um teste de arquivo;favor não quevra lalalalal"

Nice!
ficou mesmo! somente usou a concatenação.
Mas a idéia do colega Hebertbc facilita ainda mais… vc especifica qts tokens tem e joga num array!
Precisando, às ordens!

Não testei, mas acho que com regex você faria isso ai com 4 caracteres .*?;

[quote=surfzera]funciono a ideia a cima… fiz mais simple acho!

so acresentei e depois setei o valor.

dadosObs = st.nextToken();
while(st.hasMoreTokens()){
dadosObs = dadosObs + st.nextToken();
}[/quote]
Use a solução do Hebertbc por 2 motivos:

  1. Não há porque usar StringTokenizer se ele menos poderoso, mais difícil de usar e talvez mais lento que String.split
  2. Nunca concatene Strings dentro de laços de repetição. Strings são imutáveis e a cada concatenação feita novas Strings são criadas, o que torna o código extremamente lento e ineficiente. Use StringBuilder.

Sem falar no que diz o próprio javadoc da classe StringTokenizer (negrito por minha conta):

Rode o código abaixo com a opção -server e a opção -client. Quando a opção usada é -server, o String.split é mais rápido que o StringTokenizer.

import java.util.*;
import java.util.regex.*;

class BenchmarkSplit {
    public BenchmarkSplit() {
    }
    private void testSplit() {
        for (int i = 0; i < samples.length; ++i) {
            String[] parts = samples[i].split (";");
        }
    }
    private void testSmartSplit() {
        Pattern pat = Pattern.compile (";");
        for (int i = 0; i < samples.length; ++i) {
            String[] parts = pat.split (samples[i]);
        }
    }
    private void testStringTokenizer() {
        for (int i = 0; i < samples.length; ++i) {
            StringTokenizer st = new StringTokenizer (samples[i], ";");
            while (st.hasMoreTokens()) {
                String s = st.nextToken();
            }
        }
    }
    private String generateSample() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0, n = r.nextInt (10); i < n; ++i) {
            sb.append (r.nextInt()).append (";");
        }
        sb.append (r.nextInt());
        return sb.toString();
    }
    private void generateSamples() {
        for (int i = 0; i < samples.length; ++i) {
            samples[i] = generateSample();
        }
    }
    public void test() {
        generateSamples();
        long t = System.currentTimeMillis();
 	for (int i = 1; i <= 10; ++i) {
            testStringTokenizer();
        }
        System.out.printf ("%d ms%n", System.currentTimeMillis() - t);
        t = System.currentTimeMillis();
 	for (int i = 1; i <= 10; ++i) {
            testSplit();
        }       
        System.out.printf ("%d ms%n", System.currentTimeMillis() - t);
        t = System.currentTimeMillis();
 	for (int i = 1; i <= 10; ++i) {
            testSmartSplit();
        }       
        System.out.printf ("%d ms%n", System.currentTimeMillis() - t);
    }
    private String[] samples = new String[1000000];
    private Random r = new Random (0x123456789ABCDEFL);
    public static void main (String[] args) {
         new BenchmarkSplit().test();
    }
}