In-Memory Streams in Java

Naveen AnamaneniUpdated · 4 min read
easyJava 25javaiostreams

In-memory streams are streams whose source or destination is memory, such as a byte array or a string, instead of a file. They are used to test code that expects a stream without creating real files, to collect output into a string or byte array, and to pass data in memory to an API that only accepts streams. The main classes are ByteArrayInputStream and ByteArrayOutputStream for bytes, and StringReader and StringWriter (plus CharArrayReader and CharArrayWriter) for characters. In this lesson, you will learn how to use them.

The Classes

ClassDescription
ByteArrayInputStream(byte[] buf)It is used to read bytes from an array.
ByteArrayOutputStream()It collects written bytes in a growing array; get them with toByteArray() or toString(charset).
StringReader(String s)It reads characters from a string.
StringWriter()It collects written characters; get them with toString().
CharArrayReader(char[] buf)It reads characters from a char[].
CharArrayWriter()It collects characters; get them with toCharArray() or toString().

None of these need closing to release resources, because they don't hold files or sockets; closing them is harmless.

Example: Collecting Output in Memory

Let's see an example that writes a report into a StringWriter and bytes into a ByteArrayOutputStream.

Collect.java▶ Try it
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
 
public class Collect {
    public static void main(String[] args) throws IOException {
        StringWriter text = new StringWriter();
        try (PrintWriter out = new PrintWriter(text)) {
            out.printf("Navika: %d%n", 91);
            out.printf("Srihitha: %d%n", 78);
        }
        System.out.print(text);
        System.out.println(text.toString().length() + " characters");
 
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        try (DataOutputStream data = new DataOutputStream(bytes)) {
            data.writeInt(258);
        }
        System.out.println(Arrays.toString(bytes.toByteArray()));
    }
}
Output
Navika: 91
Srihitha: 78
24 characters
[0, 0, 1, 2]

Explanation: The PrintWriter writes into a StringWriter instead of a file, so the whole report ends up in a string. The DataOutputStream writes into a ByteArrayOutputStream; the int 258 becomes the four bytes 0, 0, 1, 2 (258 = 1 x 256 + 2).

Example: Testing a Method with In-Memory Input

CountLines.java▶ Try it
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
 
public class CountLines {
    static int countNonBlank(Reader source) throws IOException {
        try (BufferedReader r = new BufferedReader(source)) {
            return (int) r.lines().filter(l -> !l.isBlank()).count();
        }
    }
 
    public static void main(String[] args) throws IOException {
        String sample = """
            Navika

            Srihitha
            Advitha
            """;
        System.out.println(countNonBlank(new StringReader(sample)));
    }
}
Output
3

Explanation: countNonBlank accepts any Reader. In real use it might get a FileReader, but a StringReader lets you test it with a text block, without creating any file.

Common Mistakes

Calling toString() on a ByteArrayOutputStream holding non-ASCII text without a charset. Use toString(StandardCharsets.UTF_8).

Expecting StringWriter to be thread-safe for heavy use. It uses a StringBuffer internally, but building text in one thread with StringBuilder is usually simpler.

Practice

  1. Easy: Use a ByteArrayInputStream over the bytes of "Advitha" and print each byte as a number.
  2. Harder: Write a method void writeCsv(List<String[]> rows, Writer out), and test it by writing into a StringWriter and checking the result.

Quick check: In-memory streams

4 questions
1Which class collects written characters into a string?
2How do you get the bytes from a ByteArrayOutputStream?
3Do in-memory streams need closing to release files?
4Why are in-memory streams useful in tests?

Key Takeaways

Was this tutorial helpful?

Lesson 349 of 482