Stream vs WriterReader API

Streams 提供对二进制内容的最直接访问,因此任何 InputStream / OutputStream 实现始终在 ints 和 bytes 上运行。

// Read a single byte from the stream
int b = inputStream.read();
if (b >= 0) { // A negative value represents the end of the stream, normal values are in the range 0 - 255
    // Write the byte to another stream
    outputStream.write(b);
}

// Read a chunk
byte[] data = new byte[1024];
int nBytesRead = inputStream.read(data);
if (nBytesRead >= 0) { // A negative value represents end of stream
    // Write the chunk to another stream
    outputStream.write(data, 0, nBytesRead);
}

有一些例外,可能最值得注意的是 PrintStream 增加了方便地打印各种数据值表示的能力。这允许使用 System.out 作为二进制 InputStream 并使用诸如 System.out.println() 之类的方法作为文本输出。

此外,一些流实现用作更高级内容的接口,例如 Java 对象(请参阅序列化)或本机类型,例如 DataOutputStream / DataInputStream

通过 WriterReader 类,Java 还为显式字符流提供 API。虽然大多数应用程序都将这些实现基于流,但字符流 API 不会公开任何二进制内容的方法。

// This example uses the platform's default charset, see below
// for a better implementation.

Writer writer = new OutputStreamWriter(System.out);
writer.write("Hello world!");

Reader reader = new InputStreamReader(System.in);
char singleCharacter = reader.read();

每当需要将字符编码为二进制数据时(例如,当使用 InputStreamWriter / OutputStreamWriter 类时),如果你不想依赖于平台的默认字符集,则应指定字符集。如有疑问,请使用与 Unicode 兼容的编码,例如所有 Java 平台都支持的 UTF-8。因此,你应该远离像 FileWriterFileReader 这样的类,因为那些总是使用默认的平台字符集。使用字符流访问文件的更好方法是:

Charset myCharset = StandardCharsets.UTF_8;

Writer writer = new OutputStreamWriter( new FileOutputStream("test.txt"), myCharset );
writer.write('Ä');
writer.flush();
writer.close();

Reader reader = new InputStreamReader( new FileInputStream("test.txt"), myCharset );
char someUnicodeCharacter = reader.read();
reader.close();

最常用的 Reader 之一是 BufferedReader,它提供了一种从另一个读取器读取整行文本的方法,并且可能是逐行读取字符流的最简单方法:

// Read from baseReader, one line at a time
BufferedReader reader = new BufferedReader( baseReader );
String line;
while((line = reader.readLine()) != null) {
  // Remember: System.out is a stream, not a writer!
  System.out.println(line);
}