Ajuda com algumas classes da API java.io

Bom pessoal estou fazendo um programinha que lê o um log(arquivo txt) e procurar por possíveis erros para escreve-los em um outro arquivo e quando um erro é achado eu preciso que um numero x de linhas acima para dar um contexto ao erro

bom eu estava pensando em usar LineNumberReader.getLinerNumber, mas não sei se faz o que desejo fazer.

O que fazer?? qual classe e qual método usar?

Desde já, Muito Obrigado

Você precisa obter 20 linhas acima (por exemplo)?
Crie uma fila circular de tamanho limitado* (contendo no máximo 20 entradas), e vá inserindo as linhas que você já leu. Quando encontrar um erro, então você já tem as últimas 20 linhas.

  • Para criar uma fila dessas, use um array mesmo. Se quiser, use um java.util.LinkedList, que implementa a interface Queue, mas aí você tem de se lembrar de remover os elementos que excederem a quantidade de 20 à medida que forem inseridos.

utilize a api FileUtils do projeto apache commons io. O método FileUtils.read retorna um List, ai é só vc iterar o list.

abraços.

me deram essa ideia de fazer um buffer circular… mas nunca precisei fazer isso e não tenho a menor idéia de como começar

alguém se habilita?

class BufferCircular<E> extends LinkedList<E> {
    @Override
    public boolean add (E e) {
        // Antes de inserir, cheque se o tamanho (size) é >= 20 (por exemplo). 
        // Se for >= 20, vá removendo elementos do início, com o método poll, 
        // até que o tamanho fique no valor desejado. Então você pode
        // chamar super.add (e).
    }
}

então… olha só como estou fazendo:

private void procuraErros() throws IOException { int contador = 0; try { String caminhoArquivo = "C:" + File.separator + "FJ21" + File.separator + "io" + File.separator + "SJMG.txt";// testar // .out File f = new File(caminhoArquivo); if (f.exists()) { System.out.println("arquivo existente!"); } FileReader file = new FileReader(f); BufferedReader br = new BufferedReader(file); String s = null; while ( ((s = br.readLine() ) != null) && (!isDelimitador(br.readLine() )) ) { reader[contador] = s; // listBuffer.add(s); if (isErro(reader[contador]) ){ ExibeErros(reader[contador], contador); } if (contador == 4){ contador = -1; } contador ++; } br.close(); } catch (FileNotFoundException ex) { System.out.println("ERRO"); ex.printStackTrace(); } }

fiz usando array msm de cinco posições e qdo chega no limite vai trocando as strings… e quando acha um erro é pra exibir as 5 linhas acima ae fiz um outro método para isso, de acordo com a posição do erro:

[code]private void ExibeErros(String texto, int cont) throws IOException{
switch (cont){
case 0:
System.out.println(reader[1]);
System.out.println(reader[2]);
System.out.println(reader[3]);
System.out.println(reader[4]);
System.out.println(reader[0]);
break;

	case 1:
		System.out.println(reader[2]);
		System.out.println(reader[3]);
		System.out.println(reader[4]);
		System.out.println(reader[0]);
		System.out.println(reader[1]);
	break;
	
	case 2:
		System.out.println(reader[3]);
		System.out.println(reader[4]);
		System.out.println(reader[0]);
		System.out.println(reader[1]);
		System.out.println(reader[2]);
	break;
	
	case 3:
		System.out.println(reader[4]);
		System.out.println(reader[0]);
		System.out.println(reader[1]);
		System.out.println(reader[2]);
		System.out.println(reader[3]);
	break;
	
	case 4:
		for(int i = 0; i < reader.length; i++)
			System.out.println(reader[i]);
	break;
	}
	
	
}[/code]

mas estou com um grande problema pois quando ele acha um erro ele está exibindo duas vezes e sempre com a mesma linha antecedente

…alguém pra em ajudar???

Não use array. Como você viu, é mais difícil usar arrays que você imagina.
Eu já comecei a classe (que usa uma LinkedList) para você, se você for esperto vai conseguir terminar.

[quote=thingol] class BufferCircular&lt;E&gt; extends LinkedList&lt;E&gt; { @Override public boolean add (E e) { // Antes de inserir, cheque se o tamanho (size) é &gt;= 20 (por exemplo). // Se for &gt;= 20, vá removendo elementos do início, com o método poll, // até que o tamanho fique no valor desejado. Então você pode // chamar super.add (e). } } [/quote]

mas eu uso o poll no parametro do método???

Tá bom, eu tinha pensado nisto aqui:

import java.util.*;

/**
 * Implementação boba de uma fila de tamanho limitado.
 * Esta implementação, em vez de usar um array eficiente, simplesmente 
 * sobrecarrega um LinkedList.
 */
class BufferCircular&lt;E&gt; extends LinkedList&lt;E&gt;{
    private int capacidade;
    /**
     * Construtor.
     * @param capacidade_ O tamanho máximo do buffer. 
     */
    public BufferCircular (int capacidade_) {
        capacidade = capacidade_;
    }
    @Override 
    public boolean add (E e) {  
        // Antes de inserir, cheque se o tamanho (size) é &gt;= 20 (por exemplo).   
        // Se for &gt;= 20, vá removendo elementos do início, com o método poll,   
        // até que o tamanho fique no valor desejado. Então você pode  
        // chamar super.add (e).  
        while (size() &gt;= capacidade) {
            poll();
        }
        super.add (e);
        return true;
    } 
}

class TesteBufferCircular {
    public static void main(String[] args) {
        // Vamos pegar apenas as últimas 10 entradas. 
        BufferCircular&lt;String&gt; buf = new BufferCircular&lt;String&gt;(10);
        for (int i = 1; i &lt;= 200; ++i) {
            buf.add (&quot;Linha &quot; + i);
        }
        // Agora vamos listar os elementos.
        for (String s : buf) {
            System.out.println (s);
        }
    }
}

existe algum método onde eu recupero o indice do elemento… pois tenho que usa-los para fazer comparações

Por favor, olhe a documentação de java.util.LinkedList, que é a classe-base de BufferCircular.

sei que estou sendo um pouco folgado mas
poxa amigo… não saco nada de inglês to no inicio do curso ainda
=
da essa força ae

Tá bom, onde eu escrevi

         for (String s : buf) {  
             System.out.println (s);  
         } 

troque por

        for (int i = 0; i &lt; buf.size(); ++i) {
            System.out.println (buf.get(i));
        }

O código é equivalente e faz a mesma coisa. Por favor, compile e rode o programa para ver o que ele faz.

eu to testando sempre… e está rodando perfeitamente… só que ao invés dele mostrar as 4 linhas antecedentes ao erro + o erro… e depois fazer o mesmo para outro erro ele acha o primeiro erro e mostrar repetidamente as mesmas coisas

Acho que você ainda não entendeu como é que se deve usar isso. A idéia é fazer o seguinte (em pseudo-código):

while (não se acabaram as linhas) {
    leia uma linha;
    chame BufferCircular.add (como você deve ter feito);
    cheque se a linha contém um erro;
    se ela contiver um erro, imprima o conteúdo de BufferCircular, que deve ter as N linhas (as N-1 antecedentes ao erro, e a linha correspondente ao erro). 
}

Não é para jogar TODAS as linhas lidas em um array. Sua memória vai se esgotar antes disso.

[quote=thingol]Acho que você ainda não entendeu como é que se deve usar isso. A idéia é fazer o seguinte (em pseudo-código):

while (não se acabaram as linhas) {
    leia uma linha;
    chame BufferCircular.add (como você deve ter feito);
    cheque se a linha contém um erro;
    se ela contiver um erro, imprima o conteúdo de BufferCircular, que deve ter as N linhas (as N-1 antecedentes ao erro, e a linha correspondente ao erro). 
}

Não é para jogar TODAS as linhas lidas em um array. Sua memória vai se esgotar antes disso.
[/quote]

while ( ((s = br.readLine() ) != null) && (!isDelimitador(br.readLine() )) ) { buf.add(s); if (isErro(buf.get(contador)) ){ ExibeErros(buf.get(contador), contador); } if (contador == 4){ contador = -1; } contador ++; }

método isErro:

private boolean isErro(String s) throws IOException{ for(int i = 0; i&lt; patErros.length; i++){ Matcher match = patErros[i].matcher(s); if (match.find() ){ return true; } } return false; }

método ExibeErros:

private void ExibeErros(String texto, int cont) throws IOException{ for (int i = 0; i &lt; buf.size(); i++) System.out.println(buf.get(i)); }

 while ( ((s = br.readLine() ) != null) && (!isDelimitador(br.readLine() )) ) {  
                 buf.add(s);  
                 if (isErro(buf.get(contador)) ){  
                     ExibeErros(buf.get(contador), contador);  
                     }  
                 if (contador == 4){  
                     contador = -1;  
                 }  
                 contador ++;  
             } 

Por que esse contador agora?

 while ( ((s = br.readLine() ) != null) && (!isDelimitador(br.readLine() )) ) {  
                 buf.add(s);  
                 if (isErro(s) )
                     exibeErro(buf);   
 } 
public static void exibeErro(BufferCircular buffer){
for(int i = 0; i < buffer.size();i++)
System.out.println(buffer.get(i));
}

E se voce quiser que após exiber o conteudo do Buffer é só usar o método clear.