"Hi, Amigo!"

"Hi, Ellie!"

"Today I want to tell you about the StringReader and StringWriter classes. In principle, there won't be much that will be new to you, but sometimes these classes are very useful. But, at the very least, I want you to know that they exist."

"These classes are the simplest implementations of the abstract Reader and Writer classes. And they are basically similar to FileReader and FileWriter. However, unlike those, these don't work with data in a file on disk. Instead, they work with a String in the JVM's memory."

"Why would we need such classes?"

"Sometimes they are needed. Essentially, StringReader is an adapter between the String and Reader classes. And StringWriter is a String that inherits Writer. Yeah... I can tell that's not the best explanation. It will be better to look at a couple of examples first."

"For example, suppose you want to test your method, which reads data from the Reader object passed to it. We could do it like this:"

Reading from a Reader object:
public static void main (String[] args) throws Exception
{
 String test = "Hi!\n My name is Richard\n I'm a photographer\n";

 // This line is key: we "convert" the String into a Reader.
 StringReader reader = new StringReader(test);

 executor(reader);
}

public static void executor(Reader reader) throws Exception
{
 BufferedReader br = new BufferedReader(reader);
 String line;
 while (line = br.readLine() != null)
 {
 System.out.println(line);
 }
}

"In other words, we simply took a String, wrapped it in a StringReader, and then passed that instead of a Reader object? And everything will be read from it like we need?"

"Yep. Hmm. And there's a point to this. Now let's test the methods of StringWriter. To do this, we'll make the example more complicated. Now it won't simply read the lines and display them on the screen, instead it will reverse them and output them to the writer object. For example:"

Reading from the reader object and writing to the writer object:
public static void main (String[] args) throws Exception
{
 // The Reader must read this String.
 String test = "Hi!\n My name is Richard\n I'm a photographer\n";

 // Wrap the String in a StringReader.
 StringReader reader = new StringReader(test);

 // Create a StringWriter object.
 StringWriter writer = new StringWriter();

 // Copy strings from the Reader to the Writer, after first reversing them.
 executor(reader, writer);

 // Get the text that was written to the Writer.
 String result = writer.toString();

 // Display the text from the Writer on the screen.
 System.out.println("Result: "+ result);
}

public static void executor(Reader reader, Writer writer) throws Exception
{
 BufferedReader br = new BufferedReader(reader);
String line;

 // Read a string from the Reader.
while (line = br.readLine()) != null)
 {

 // Reverse the string.
  StringBuilder sb = new StringBuilder(line);
  String newLine = sb.reverse().toString();

 // Write the string to the Writer.
  writer.write(newLine);
 }
}

"We created a StringWriter object that contains a string that stores everything written to this writer. And to get it, you just need to call the toString() method."

"Hmm. Somehow it all seems too easy. The executor method works with the reader and writer stream objects, but we're working with strings in the main method.

"Is it all really that simple?"

"Yep. To convert a String to a Reader, just write this:"

Creating a Reader from a String
String s = "data";
Reader reader = new StringReader(s);

"And converting a StringWriter to a String is even easier:"

Getting a String from a Writer
Writer writer = new StringWriter();
/* Here we write a bunch of data to the writer */
String result = writer.toString();

"These are excellent classes, in my opinion. Thanks for telling me about them, Ellie."