1. InputStreamReader
aula
Outro recurso interessante dos fluxos é que você pode combinar vários fluxos em cadeias . Um fluxo pode ler dados não apenas de sua fonte de dados interna, mas também de outro fluxo .
Este é um mecanismo muito poderoso em Java, que permite criar cenários complexos de leitura de dados conectando um fluxo a outro. Tal esquema se parece com isso:
Quando um programa lê dados de um fluxo de dados, o fluxo de dados, por sua vez, lê os dados de sua fonte de dados, que é outro fluxo de dados ou um arquivo, por exemplo.
Além do mais, cada fluxo de dados não apenas lê e distribui dados, mas também pode transformá-los ou realizar várias operações neles. Um bom exemplo desse "fluxo intermediário" é a InputStreamReader
classe.
Já conhecemos uma classe chamada FileReader
— é uma Reader
que lê dados de um arquivo. E InputStreamReader
de onde obtém seus dados? Isso mesmo - de um arquivo InputStream
.
Ao criar um InputStreamReader
objeto, você precisa passar um InputStream
objeto ou uma de suas classes descendentes. Exemplo:
String src = "c:\\projects\\log.txt";
FileInputStream input = new FileInputStream(src);
InputStreamReader reader = new InputStreamReader(input);
A InputStreamReader
classe tem todos os métodos que a Reader
classe tem e eles funcionam exatamente da mesma maneira.
A principal diferença entre a InputStreamReader
classe e, digamos, FileReader
é de onde eles leem os dados. FileReader
lê dados de um arquivo (duh - é por isso que é chamado FileReader
), mas InputStreamReader
lê dados de um arquivo InputStream
.
Quando você lê um caractere de um FileReader
objeto usando o read()
método, ele, por sua vez, lê dois bytes do arquivo no disco e os retorna como chars
.
Quando você lê um caractere de um InputStreamReader
objeto usando o read()
método, ele, por sua vez, lê dois bytes do FileInputStream
objeto passado para ele, que por sua vez lê os dados do arquivo. O resultado é uma cadeia de chamadas para read()
métodos.
2. BufferedReader
classe
Outra classe interessante que você provavelmente usará muito é BufferedReader
. Este também é um "fluxo intermediário" que lê dados de outro fluxo.
Como o próprio nome sugere, a BufferedReader
classe é uma subclasse de Reader
e permite que você leia caracteres . Mas o mais interessante é que você também precisa passar para ela uma fonte de dados na forma de um stream a partir do qual os caracteres podem ser lidos , ou seja, um stream que herda a Reader
classe.
Qual é o ponto? Ao contrário de InputStreamReader
, a BufferedReader
classe não converte bytes em caracteres: ela não converte absolutamente nada. Em vez disso, ele armazena os dados em buffer .
Quando um programa lê um único caractere de um BufferedReader
objeto, o objeto lê uma grande variedade de caracteres de seu fluxo de origem de uma só vez. E os armazena internamente.
Quando o próximo caractere é lido do BufferedReader
objeto, ele simplesmente pega o próximo caractere de sua matriz de buffer interno e o retorna sem acessar a fonte de dados. Somente quando todos os caracteres no buffer são usados, ele lê em outra grande matriz de caracteres.
A BufferedReader
classe também tem um método muito útil — String readLine()
, que permite ler sequências inteiras de dados do fluxo de origem de uma só vez. Você pode usar esse método para, digamos, ler um arquivo e exibir seu conteúdo na tela linha por linha. Exemplo:
Escrevemos especificamente um código compacto para ilustrar como isso pode ser conveniente. Esse código também poderia ser escrito com um pouco mais de detalhes.
|
Crie um FileReader objeto. A fonte de dados é um arquivo. Crie um BufferedReader objeto. A fonte de dados é um arquivo FileReader . Enquanto ainda houver dados no leitor Leia uma linha Exiba a linha |
Se você encadear vários fluxos, o close()
método só precisará ser chamado em um deles. Esse fluxo chamará o método em sua fonte de dados e assim por diante, até close()
ser chamado no fluxo de dados final.
3. Lendo no console
E mais um fato interessante: a Scanner
classe nada mais é do que um fluxo de entrada intermediário que lê dados de System.in
, que também é um fluxo de dados.
Aqui estão duas maneiras de ler uma linha do console:
classe do scanner | Classes BufferedReader e BufferedWriter |
---|---|
|
|
Nosso amigo nada mais é do que uma variável estática da classe. É um cujo nome é .System.in
in
System
InputStream
in
Assim, quase desde o início de seus estudos de Java no CodeGym, você trabalhou com fluxos de dados e construiu cadeias a partir deles. Mas agora você fará isso de forma mais consciente.