It's sometimes convenient to use a string as a source of data or a target for output. Since Java strings are made of Unicode characters, this requires readers and writers. The java.io.StringReader class is initialized with a string and then reads successive characters from the string. The java.io.StringWriter class writes output into a string, a character at a time, expanding the output string as necessary. Unlike most other readers and writers, the StringReader and StringWriter classes do not perform character set conversions. Since these classes operate completely inside Java, all reading and writing takes place in Unicode.
In Java 1.1, the `StringReader` and `StringWriter` classes provide efficient ways to read and write character data using in-memory strings without character set conversions. Let's break down their usage with examples.
 1. Using StringReader to Read a String Character by Character
The `StringReader` class allows reading characters from a `String` as if it were an input stream.
Example: Reading from a String
import java.io.StringReader;
import java.io.IOException;
public class StringReaderExample {
    public static void main(String[] args) {
        String data = "Hello, Java 1.1!";
        try (StringReader reader = new StringReader(data)) {
            int character;
            while ((character = reader.read()) != -1) { // Read character by character
                System.out.print((char) character);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Output:
Hello, Java 1.1!
This demonstrates how `StringReader` reads a string as a character stream.
2. Using StringWriter to Write a String
 
The `StringWriter` class writes character data into an internal `StringBuffer`, dynamically growing as needed.
Example: Writing to a String
import java.io.StringWriter;
import java.io.IOException;
public class StringWriterExample {
    public static void main(String[] args) {
        try (StringWriter writer = new StringWriter()) {
            writer.write("Java 1.1 StringWriter Example"); // Write characters
            writer.write(" - Efficient string handling!"); // Append more data
            
            // Convert StringWriter to a String
            String output = writer.toString();
            
            System.out.println("Written Data: " + output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Output:
Written Data: Java 1.1 StringWriter Example - Efficient string handling!
This shows how `StringWriter` accumulates text data dynamically in memory.
 
Key Differences: `StringReader` vs `StringWriter`
    
      | Feature | `StringReader` | `StringWriter` | 
    
      | Purpose | Reads from a string | Writes to an expandable string | 
    
      | Initialization | Takes a `String` as input | Creates an internal buffer to store written characters | 
    
      | Output Retrieval | Read characters one by one | Uses `toString()` to retrieve written data | 
    
      | Use Case | Processing a string as an input stream | Efficiently building a string dynamically | 
  
These classes are useful when you need to manipulate text in memory without dealing with file I/O or character encoding conversions.
The 
StringReader class has the usual methods of 
Reader classes plus one constructor. 
StringReaders do support marking and resetting.
public StringReader(String s)
The StringWriter class
The 
StringWriter class has the usual methods of 
Writer classes plus one public constructor:
public StringWriter()
You can use the 
toString() method to return the 
String that's been written with this writer. Alternatively, the 
getBuffer() method returns the internal 
java.lang.StringBuffer object used by this 
StringWriter.
public String toString()
public StringBuffer getBuffer()