1. Overview
In this article, we’ll discuss the InputStream class and how it can handle binary information from various sources. We’ll also discuss the InputStreamReader class and its differences compared to an InputStream.
2. What is InputStream
InputStream is a class that reads binary data in the form of bytes from a source. Because it is an abstract class, we can only instantiate it through its subclasses, FileInputStream and ByteArrayInputStream, to name a few.
3. What is InputStreamReader
Compared with the InputStream class, InputStreamReader deals directly with characters or text. It reads bytes using the given InputStream and then converts them into characters based on a certain Charset. We can explicitly set the Charset, some of them are UTF-8, UTF-16, et cetera, or rely on the JVM’s default charset:
@Test
public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException {
String sampleTxt = "Good day. This is just a test. Good bye.";
Path sampleOut = tempDir.resolve("sample-out.txt");
List<String> lines = Arrays.asList(sampleTxt);
Files.write(sampleOut, lines);
String absolutePath = String.valueOf(sampleOut.toAbsolutePath());
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8)) {
boolean isMatched = false;
int b;
StringBuilder sb = new StringBuilder();
while ((b = reader.read()) != -1) {
sb.append((char) b);
if (sb.toString().contains(sampleTxt)) {
isMatched = true;
break;
}
}
assertThat(isMatched).isTrue();
}
}
The code snippet above demonstrates how we could use the StandardCharsets.UTF_8 constant to explicitly set the encoding for the InputStreamReader.
Our FileInputStream, a type of InputStream, is wrapped with an InputStreamReader. Hence, we can see that InputStreamReader interprets the InputStream as text rather than raw byte information.
4. InputStreamReader versus InputStream
InputStreamReader is a bridge from byte streams to character streams. This class takes an InputStream instance, reads bytes, and decodes them into characters using a character encoding. It has a read() method that reads a single character. This method converts bytes to characters by reading one or more bytes ahead of its current location in the underlying InputStream. When the end of the stream has been reached, it returns -1.
In contrast, InputStream is a superclass for all classes representing an input stream of bytes. This class is the main constructor parameter of InputStreamReader, meaning any subclasses of InputStream are valid byte sources for InputStreamReader.
The InputStream class also has a read() method that reads a single byte. However, the InputStream.read() method does not decode bytes into characters, whereas an InputStreamReader.read() does.
5. Conclusion
In this article, we discussed the InputStream and InputStreamReader. An InputStream is an abstract class with various subclasses that tend to specific forms of binary data, FileInputStream and ByteArrayInputStream, to name a few. In contrast, InputStreamReader reads bytes from an InputStream and converts them into characters of a specified encoding.
The difference between these two classes is straightforward. When we need to work with binary data, we should use an InputStream. If we need to work with character streams, we may benefit from using an InputStreamReader.
An InputStream is the main constructor parameter needed to create an InputStreamReader.
All code samples used in the article are available over on GitHub.