1. 概述

在这篇文章中,我们将探讨InputStream类以及它如何处理来自不同源的二进制信息。我们还将讨论InputStreamReader类,并与InputStream进行比较。

2. InputStream是什么?

InputStream是一个类,它从源读取以字节形式存在的二进制数据。由于它是抽象类,我们只能通过其子类,如FileInputStreamByteArrayInputStream等,来实例化它。

3. InputStreamReader是什么?

相比InputStream类,InputStreamReader直接处理字符或文本。它使用给定的InputStream读取字节,然后根据特定的字符集(Charset)将它们转换为字符。我们可以明确设置字符集,例如UTF-8、UTF-16等,也可以依赖JVM的默认字符集:

@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();
    }
}

上面的代码示例展示了如何使用StandardCharsets.UTF_8常量来显式设置InputStreamReader的编码。

我们的FileInputStream,即InputStream的一种类型,被InputStreamReader包装。因此,我们可以看到InputStreamReaderInputStream解释为文本,而不是原始字节信息。

4. InputStreamReaderInputStream

InputStreamReader是字节流到字符流的桥梁。这个类接受一个InputStream实例,读取字节,并使用字符编码将其解码。它有一个read()方法,用于读取单个字符。此方法通过在其底层InputStream当前位置之前读取一或多个字节来将字节转换为字符。当到达流的末尾时,它返回-1。

相比之下,InputStream是所有表示字节输入流的类的超类。InputStreamReader的构造函数的主要参数就是InputStream,这意味着InputStream的所有子类都是InputStreamReader的有效字节源。

InputStream类也有一个read()方法,用于读取单个字节。然而,InputStream.read()方法并不解码字节为字符,而InputStreamReader.read()则会。

5. 总结

在这篇文章中,我们讨论了InputStreamInputStreamReaderInputStream是一个抽象类,拥有多个子类,专门针对特定形式的二进制数据,如FileInputStreamByteArrayInputStream等。相反,InputStreamReaderInputStream读取字节并将其转换为指定编码的字符。

这两个类之间的区别很简单。当我们需要处理二进制数据时,应使用InputStream。如果需要处理字符流,使用InputStreamReader可能会有帮助。

创建InputStreamReader时,InputStream是主要的构造参数。

文章中使用的所有代码示例可在GitHub上找到。