quarta-feira, julho 27, 2005

Ler arquivos... Que coisa chata

Sempre que preciso ler um arquivo de texto, principalmente quando precisa recuperar linha a linha o JAVA me faz criar um monte de objetos, depois colocar dentro de um Loop com uma decisão que me deixa confuso...

Veja como é chato:
BufferedReader reader = new BufferedReader(new FileReader("myFile"));
String aLine = null;
while((aLine = reader.readLine()) != null) {
// do the job
}


Este tipo de decisão só complica a leitura do código.

Então numa desta noites, antes de cair no sono, leio num livro um modo legal de encapsular este tipo de leitura de modo a poder utilizar a interface Iterator.

Achei legal a idéia e fiz uma cópia/implementação do que vi lá.
package br.com.dadario.file;

import java.io.*;
import java.util.Iterator;

public class ReadFile {

private File file;

public ReadFile(String filename) {
this.file = new File(filename);
if (!file.exists() && !file.canRead()) {
throw new IllegalArgumentException("Invalid file to open");
}
}

public Iterator iterator() {
try {
return new MyIterator(new BufferedReader(new FileReader(file)));
} catch (FileNotFoundException e) {
throw new IllegalArgumentException("File not found.");
}
}

class MyIterator implements Iterator {

private BufferedReader reader;
private String aLine = null;

MyIterator(BufferedReader reader) {
this.reader = reader;
try {
aLine = reader.readLine();
} catch (IOException e) {
aLine = null;
}
}

public void remove() {
throw new UnsupportedOperationException("It's not possible remove lines from file.");
}

public boolean hasNext() {
return aLine != null;
}

public Object next() {

String value = aLine;

try {
aLine = reader.readLine();
} catch (IOException e) {
aLine = null;
}

if (!hasNext()) {
try {
reader.close();
} catch (IOException e) {
// Just close
}
}

return value;
}
}
}

O legal desta implementação é que posso iteragir nas linha com o Iterator do JAVA, então as estruturas abaixo são válidas:
public static void main(String[] args) {

ReadFile file = new ReadFile("myFile");

for (Iterator iter = file.iterator(); iter.hasNext();) {
String element = (String) iter.next();
System.out.println(element);
}

System.out.println("Twice...");

Iterator iterator = file.iterator();
while (iterator.hasNext()) {
String element = (String) iterator.next();
System.out.println(element);
}
}

Não preciso mais me preocupar com aquela decisão... E sim com a iteração.

Outro ponto que achei interessante colocado no livro é o fato de poder utilizar o mesmo esquema de código para iteragir com o novo esquema do Java Tiger, o FOR/IN.

Para isto, basta apenas fazer a classe ReadFile implementar a interface Iterable
public class ReadFile implements Iterable {
// BODY
}


E podemos utilizar com o for/in :)
for (Object object : file) {
System.out.println(object);
}


Estas coisas práticas do dia a dia...