"Sou eu novamente."

"Oi, Ellie!"

"Hoje eu gostaria de contar tudo sobre BufferedReader e BufferedWriter ."

"Você já me contou sobre eles. Eles realmente não são tão complicados."

"OK. Então me diga como o BufferedReader funciona."

" BufferedReader é como um conversor de 110/220V."

"Você tem que passar para o construtor BufferedReader o objeto Reader do qual os dados serão lidos. Um objeto BufferedReader lê grandes blocos de dados do Reader e os armazena internamente em um buffer. É por isso que usar um BufferedReader para ler de um Reader é mais rápido do que ler diretamente de um Reader ."

"Isso mesmo. E o BufferedWriter ?"

"É muito fácil. Suponha que escrevamos em um FileWriter . Os dados são gravados no disco imediatamente. Se escrevermos pequenos bits de dados com frequência, vamos bater muito no disco, o que deixará o programa muito lento. Mas se usarmos um BufferedWriter como um 'conversor', a operação de gravação será muito mais rápida. Quando você escreve em um BufferedWriter , ele salva os dados em um buffer interno. Quando o buffer está cheio, ele grava os dados no gravador como um único pedaço grande. Isso é muito mais rápido."

"Hmm. Certo. Mas o que você esqueceu?"

"Depois de terminar de escrever, você precisa chamar o método flush() no objeto BufferedWriter para forçá-lo a enviar quaisquer dados ainda no buffer para o Writer ."

"E o que mais?"

"O que mais? Oh! Desde que o buffer não tenha sido gravado no gravador , os dados podem ser excluídos e/ou substituídos."

"Amigo! Estou impressionado! Você é um especialista! Bem, então vou falar sobre algumas novas classes:  ByteArrayStream e PrintStream ."

"Por exemplo, ByteArrayInputStream e ByteArrayOutputStream ."

"Essas classes são um pouco como StringReader e StringWriter . Exceto que StringReader lê caracteres ( char ) de uma string ( String ), mas InputStream lê bytes de uma matriz de bytes ( ByteArray )."

StringWriter grava caracteres ( char ) em uma string, enquanto ByteArrayOutputStream grava bytes em uma matriz interna de bytes. Quando você grava em um StringWriter , sua string interna fica mais longa e, quando você grava em um ByteArrayOutputStream , sua matriz de bytes interna também se expande dinamicamente.

"Lembre-se do exemplo que lhe foi dado na última lição:"

Lendo do objeto leitor e escrevendo para o objeto escritor:
public static void main (String[] args) throws Exception
{
 String test = "Hi!\n My name is Richard\n I'm a photographer\n";
 StringReader reader = new StringReader(test);

 StringWriter writer = new StringWriter();

 executor(reader, writer);

 String result = writer.toString();

 System.out.println("Result: "+ result);
}

public static void executor(Reader reader, Writer writer) throws Exception
{
 BufferedReader br = new BufferedReader(reader);
 String line;
 while ((line = br.readLine()) != null) {
 StringBuilder sb = new StringBuilder(line);
 String newLine = sb.reverse().toString();

 writer.write(newLine);
 }
}

"Aqui está como ficaria se funcionasse usando bytes em vez de caracteres:"

Lendo de um objeto InputStream e gravando em um objeto OutputStream:
public static void main (String[] args) throws Exception
{
 String test = "Hi!\n My name is Richard\n I'm a photographer\n";
 InputStream inputStream = new ByteArrayInputStream(test.getBytes());

 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

 executor(inputStream, outputStream);

 String result = new String(outputStream.toByteArray());
 System.out.println("Result: "+ result);
}

public static void executor(InputStream inputStream, OutputStream outputStream) throws Exception
{
 BufferedInputStream bis = new BufferedInputStream(inputStream);
 while (bis.available() > 0)
 {
  int data = bis.read();
  outputStream.write(data);
 }
}

"Tudo é igual ao exemplo acima. Exceto que substituímos String por ByteArray, Reader por InputStream e Writer por OutputStream."

"As duas únicas outras etapas são converter a String em um ByteArray e vice-versa. Como você pode ver, isso é feito com bastante facilidade:"

Convertendo uma String em um ByteArray e vice-versa
public static void main (String[] args) throws Exception
{
 String test = "Hi!\n My name is Richard\n I'm a photographer\n";
 byte[] array = test.getBytes();

 String result = new String(array);
 System.out.println("Result: "+ result);
}

"Para obter os bytes que já foram adicionados a um ByteArrayOutputStream, chame o método toByteArray ()."

"Ah. As semelhanças com StringReader/StringWriter são muito fortes, especialmente depois que você as apontou para mim. Obrigado, Ellie, por uma lição realmente interessante."

"Onde você está indo com tanta pressa? Ainda tenho um presentinho para você. Quero falar sobre a classe PrintStream."

"PrintStream? É a primeira vez que ouço falar dessa classe."

"Sim. Especialmente, se você não contar o fato de que você o está usando desde o primeiro dia de seus estudos de Java. Você se lembra de System.out ? Bem, System.out é uma variável estática (classe) do System class, e seu tipo é... PrintStream ! É daí que todos esses métodos print, println, etc. se originam."

"Uau. Que interessante. De alguma forma, nunca considerei isso. Conte-me mais."

"Ótimo. Ok, escute. A classe PrintStream foi inventada para saída legível. Ela consiste quase inteiramente em métodos print e println. Veja esta tabela:"

Métodos Métodos
void print(boolean b) void println(boolean b)
void print(char c) void println(char c)
void print(int c) void println(int c)
void print(long c) void println(long c)
void print(float c) void println(float c)
void print(double c) void println(double c)
void print(char[] c) void println(char[] c)
void print(String c) void println(String c)
void print(Object obj) void println(Object obj)
void println()
PrintStream format (String format, Object ... args)
PrintStream format (Locale l, String format, Object ... args)

"Também existem vários métodos de formato para que você possa enviar dados usando uma string de formato. Por exemplo:"

Convertendo uma String em um ByteArray e vice-versa
String name = "Kolan";
int age = 25;
System.out.format("My name is %s. My age is %d.", name, age);
Saída da tela:
My name is Kolan. My age is 25.

"Sim, eu me lembro. Já estudamos o método de formato da classe String."

"É tudo por agora."

"Obrigado, Ellie."