"It's me again."

"Hi, Ellie!"

"Today I'd like to tell you all about BufferedReader and BufferedWriter."

"You already told me about them. They really aren't that complicated."

"OK. Then tell me how BufferedReader works."

"BufferedReader is like a 110/220V converter."

"You have to pass to the BufferedReader constructor the Reader object that data will be read from. A BufferedReader object reads big chunks of data from the Reader and stores them internally in a buffer. That's why using a BufferedReader to read from a Reader is faster than reading directly from a Reader."

"That's right. And what about BufferedWriter?"

"It's a piece of cake. Suppose we write to a FileWriter. The data is written to disk immediately. If we write little bits of data frequently, then we'll hit the disk a lot, which will slow down the program a lot. But if we use a BufferedWriter as a 'converter', then the write operation is much faster. When you write to a BufferedWriter, it saves the data in an internal buffer. When the buffer is full, it writes the data to the Writer as a single large chunk. This is much faster."

"Hmm. Spot on. But what have you forgotten?"

"After you're done writing, you need to call the flush() method on the BufferedWriter object to force it to send any data still in the buffer to the Writer."

"And what else?"

"What else? Oh! As long as the buffer hasn't been written to the Writer, the data can be deleted and/or replaced."

"Amigo! I'm impressed! You're an expert! Well, then I'll tell you about some new classes: ByteArrayStream and PrintStream."

"For example, ByteArrayInputStream and ByteArrayOutputStream."

"These classes are a bit like StringReader and StringWriter. Except StringReader reads characters (char) from a string (String), but InputStream reads bytes from a byte array (ByteArray)."

StringWriter writes characters (char) to a string, while ByteArrayOutputStream writes bytes to an internal byte array. When you write to a StringWriter, its internal string grows longer, and when you write to a ByteArrayOutputStream its internal byte array also expands dynamically.

"Remember the example you were given in the last lesson:"

Reading from the reader object and writing to the writer object:
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();


"Here is how it would look if it worked using bytes instead of characters:"

Reading from an InputStream object and writing to an OutputStream object:
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();

"Everything is the same as in the example above. Except, we replaced String with ByteArray, Reader with InputStream, and Writer with OutputStream."

"The only two other steps are converting the String into a ByteArray and back again. As you can see, this is done quite easily:"

Converting a String into a ByteArray and back again
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);

"To get the bytes that have already been added to a ByteArrayOutputStream, call the toByteArray() method."

"Ah. The similarities to StringReader/StringWriter are pretty strong, especially after you pointed them out to me. Thank you, Ellie, for a really interesting lesson."

"Where are you off to in such a hurry? I still have a small gift for you. I want to tell you about the PrintStream class."

"PrintStream? That's the first time I've heard of that class."

"Yep. Especially, if you don't count the fact that you've been using it since day one of your Java studies. Do you remember System.out? Well, System.out is a static (class) variable of the System class, and its type is... PrintStream! This is where all of these print, println, etc. methods stem from."

"Wow. How interesting. I somehow never even considered that. Tell me more."

"Good. Okay, listen up. The PrintStream class was invented for readable output. It consists almost entirely of print and println methods. Look at this table:"

Methods Methods
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)

"There are also several format methods so you can output data using a format string. For example:"

Converting a String into a ByteArray and back again
String name = "Kolan";
int age = 25;
System.out.format("My name is %s. My age is %d.", name, age);
Screen output:
My name is Kolan. My age is 25.

"Yeah, I remember. We already studied the String class's format method."

"That's all for now."

"Thanks, Ellie."