1. OutputStreamaula

Recentemente, exploramos os fluxos de entrada. É hora de falar sobre fluxos de saída.

A OutputStreamclasse é a classe pai para todas as classes que suportam a saída de bytes. Esta é uma classe abstrata que não faz nada sozinha, mas possui classes descendentes para cada ocasião.

Parece extremamente complicado. Simplificando, essa classe opera em bytes e não, por exemplo, em caracteres ou outros tipos de dados. E o fato de ser abstrato significa que normalmente não o usamos, mas sim uma de suas classes descendentes. Por exemplo, FileOutputStreame afins.

Mas voltando à OutputStreamaula. Esta classe tem métodos que todas as suas classes descendentes devem implementar. Aqui estão os principais:

Métodos Descrição
void write(int b)
Grava um byte (não um int) no fluxo.
void write(byte[] buffer)
Grava uma matriz de bytes no fluxo
void write(byte[] buffer, off, len)
Grava parte de uma matriz de bytes no fluxo
void flush()
Grava todos os dados armazenados no buffer para o fluxo
void close()
Fecha o fluxo

Quando você cria um objeto de uma classe que herda InputStream, geralmente especifica um objeto de origem do qual InputStreamlê os dados. Quando você cria um objeto de uma classe que herda OutputStream, geralmente também especifica o objeto ou fluxo de destino no qual os dados serão gravados.

Vamos passar rapidamente por todos os métodos da OutputStreamclasse:

write(int b)método

Esse método grava um byte (não um int) no fluxo de saída. O valor passado é convertido em um byte e os três primeiros bytes do int são descartados.

write(byte[] buffer)método

Grava a matriz de bytes fornecida no fluxo de saída. É isso.

write(byte[] buffer, int offset, int length)método

Grava uma parte da matriz de bytes transmitida no fluxo de saída. A variável offset indica o índice do primeiro elemento do array, e lengthé o comprimento do subconjunto a ser escrito.

flush()método

O flush()método é usado para forçar qualquer dado potencialmente armazenado em buffer no fluxo atual a ser gravado no fluxo de destino. Isso é relevante ao usar armazenamento em buffer e/ou vários objetos de fluxo organizados em uma cadeia.

close()método

Grava todos os dados não gravados no objeto de destino. O close()método não precisa ser chamado se você usar um try-with-resourcesbloco.

Exemplo de cópia de um arquivo

Código Observação
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);
FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = new byte[65536]; // 64Kb
   while (input.available() > 0)
   {
      int real = input.read(buffer);
      output.write(buffer, 0, real);
   }
}



InputStreampara ler de um arquivo
OutputStreampara gravar em um arquivo

Buffer no qual leremos os dados
Enquanto houver dados no fluxo

Ler dados no buffer
Gravar os dados do buffer no segundo fluxo

2. Writerclasse

A Writerclasse é exatamente igual à OutputStreamclasse, mas apenas uma diferença mais uma vez: ela trabalha com caracteres ( char) em vez de bytes.

Esta é uma classe abstrata: você não pode criar objetos da Writerclasse. Seu principal objetivo é ser uma classe pai comum para centenas de classes descendentes e fornecer a elas métodos comuns para trabalhar com fluxos de caracteres.

Métodos da Writerclasse (e todas as suas classes descendentes):

Métodos Descrição
void write(int b)
Grava um caractere (não um int) no fluxo.
void write(char[] buffer)
Grava uma matriz de caracteres no fluxo
void write(char[] buffer, off, len)
Grava parte de uma matriz de caracteres no fluxo
void write(String str)
Grava uma string no stream
void write(String str, off, len)
Grava parte de uma string no stream
void flush()
Grava todos os dados armazenados no buffer para o fluxo
void close()
Fecha o fluxo

Os métodos são muito semelhantes aos métodos da OutputStreamclasse, mas trabalham com caracteres em vez de bytes.

Descrição dos métodos:

write(int b)método

Este método grava um único caractere ( char— não um int) no fluxo de saída. O valor passado é convertido em um chare os dois primeiros bytes são descartados.

write(char[] buffer)método

Grava a matriz de caracteres fornecida no fluxo de saída.

write(char[] buffer, int offset, int length)método

Grava uma parte da matriz de caracteres transmitida no fluxo de saída. A offsetvariável indica o índice do primeiro elemento da matriz e lengthé o comprimento do subconjunto a ser escrito.

write(String str)método

Grava a string fornecida no fluxo de saída.

write(String str, int offset, int length)método

Grava uma parte da string fornecida no fluxo de saída: a string é convertida em uma matriz de caracteres. A offsetvariável indica o índice do primeiro elemento da matriz e lengthé o comprimento do subconjunto a ser escrito.

flush()método

O flush()método é usado para forçar qualquer dado potencialmente armazenado em buffer no fluxo atual a ser gravado no fluxo de destino. Isso é relevante ao usar armazenamento em buffer e/ou vários objetos de fluxo organizados em uma cadeia.

close()método

Grava todos os dados não gravados no objeto de destino. O close()método não precisa ser chamado se você usar um try-with-resourcesbloco.

Exemplo de um programa que copia um arquivo de texto:

Código Observação
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileReader reader = new FileReader(src);
FileWriter writer = new FileWriter(dest))
{
   char[] buffer = new char[65536]; // 128Kb
   while (reader.ready())
   {
      int real = reader.read(buffer);
      writer.write(buffer, 0, real);
   }
}



Readerpara ler de um arquivo
Writerpara gravar em um arquivo

Buffer no qual leremos os dados
Enquanto houver dados no fluxo

Ler dados em um buffer
Gravar os dados do buffer no segundo fluxo

StringWriteraula

Existe outra classe interessante que herda a Writerclasse: ela se chama StringWriter. Ele contém uma string mutável — um StringBufferobjeto. E toda vez que você "escreve" algo no StringWriterobjeto, o texto é simplesmente adicionado ao seu buffer interno.

Exemplo:

Código Observação
StringWriter writer = new StringWriter();
writer.write("Hello");
writer.write(String.valueOf(123));

String result = writer.toString();
Um fluxo de caracteres de destino ( StringWriter) é criado
Uma string é gravada no buffer dentro do StringWriter
Uma string é gravada no buffer dentro do StringWriter

Convertendo o conteúdo de um objeto em uma string

Nesse caso, a StringWriterclasse é essencialmente um wrapper sobre a StringBufferclasse, mas a StringWriterclasse é descendente da Writerclasse de fluxo e pode ser usada em cadeias de objetos de fluxo. Esta é uma propriedade bastante útil na prática.