BufferedReader, FileReader, InputStreamReader e FileInputStream

oi!

Eu estou a tentar descubrir a melhor forma de ler e escrever ficheiros/arquivos acontece que cada exemplo que encontro usa um tipo diferente de streams.

Depois de pesquisar na net acho que qualquer uma das BufferedReader, FileReader, InputStreamReader e FileInputStream são importantes.
Parece-me que devo fazer

BufferedReader in = new BufferedReader(new FileReader("foo.in"));
Contudo nos javadocs dizem-me para criar o FileReader apartir ou de InputStreamReader ou de FileInputStream.
Alguém compreende porquê?

O que é que realmente significa estar a criar Streams umas por cima das outras?

Em alternativa alguém sabe de um site/livro(disponível na net) que explique isso direitinho?

Desde já obrigada

Olá

Essas classes pertencentes ao pacote java.oi que possuem “Reader” ou “Writer” no seu nome da classe, como em FileWriter ou FileReader, servem para trabalhar com arquivos do tipo texto.

Outra: a arquitetura I/O, em Java, foi estruturada para trabalhar em “encadeamento”. Vc sabe que arquivos trabalham com fluxos de bytes - streams.
Portanto, é necessário que os dados contidos nesses arquivos do tipo texto sejam convertidos em fluxos de bytes. Além disso, é de sua vontade que esses fluxos de bytes sejam transferidos para algum lugar, como um arquivo, por exemplo. Portanto, temos o seguinte encadeamento:

Texto >>> Bytes >>> Arquivo

Vamos para a segunda parte desse encadeamento
Bytes >>> Arquivo, que pode ser representado por:
FileInputStream finputStream = new FileInputStream(new File(“C:\arquivo.txt”));

Observe que o construtor recebe uma instancia da classe File, que nada mais faz do que representar um caminho no disco. Esse objeto seria o responsável por transferir o fluxo de bytes para o arquivo.

Vamos, agora, analisar a primeira parte:
Texto >>> Bytes, que pode ser representado por:
InputStreamReader inputStreamReader = new InputStreamReader(finputStream);

Observe que essa segunda parte recebe um InputStream - FileInputStream é um InputStream. Esse objeto seria o responsável por converter texto em fluxo de bytes.

Ao final, teremos o seguinte:
FileInputStream finputStream = new FileInputStream(new File(“C:\arquivo.txt”)); // Responsável por transferir os bytes para uma saída - nesse caso, um arquivo
InputStreamReader inputStreamReader = new InputStreamReader(finputStream); // Responsável por converter texto em bytes

Agora, é só acessar inputStreamReader atarvés do método write:

inputStreamReader.write(“Gravando no arquivo!”);

Nos bastidores, inputStreamReader converte essa String em fluxo de bytes, e acessa o método write de finputStream - obtido através do seu construtor -, passando esse fluxo de bytes obtidos a partir da String.

Abraços

Oi, você pode usar, em vez dos Streams, FileChannel, que é muito mais rápido.

Aqui tem duas formas de você obter um:

Se precisar de algum exemplo eu posso postar pra você.

Manda aí para mim esse exemplo.

Abraços

Os streams “um em cima de outro” são um exemplo de um padrão chamado Decorator.

O Stream (FileInputReader) básico faz uma tarefa simples, só lê dados do arquivo.

Mas, para ler eficientemente, você deve usar um buffer. Então, existe um stream que faz buffer de qualquer outro stream. Ele chama-se BufferedReader. Assim, associando um BufferedReader a um FileReader, você lê do arquivo usando um Buffer.

A grande vantagem de se fazer dessa forma é que você pode variar com independencia os streams. As classes também ficam flexíveis, podendo ser usadas com diferentes streams. Por exemplo, se você tiver um SocketInputStream poderia fazer buffer com ele fazendo:
BufferedReader reader = new BufferedReader(socket.getInputStream());

Existem diversos outros readers, capazes de “decorar” o reader original com as mais diversas funcionalidades. Entre elas, leitura de dados de tipos primitivos e leitura de objetos inteiros.