Java 流 vs Writer/Reader API

示例

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

// 从流中读取一个字节
int b = inputStream.read();
if (b >= 0) { // 负值表示流的结尾,正常值的范围是0-255
    // 将字节写入另一个流
    outputStream.write(b);
}

// 读取大块
byte[] data = new byte[1024];
int nBytesRead = inputStream.read(data);
if (nBytesRead >= 0) { // 负值表示流结束
    // 将块写入另一个流
    outputStream.write(data, 0, nBytesRead);
}

有一些例外,可能最显着的例外是PrintStream添加了“方便地打印各种数据值的表示形式的能力”。这允许使用诸如之类的方法System.out同时用作二进制InputStream和文本输出。System.out.println()

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

通过Writer和Reader类,Java还提供了用于显式字符流的API。尽管大多数应用程序将这些实现基于流,但是字符流API并未公开任何二进制内容的方法。

// 本示例使用平台的默认字符集,请参见下文
// 为了更好的实施。

Writer writer = new OutputStreamWriter(System.out);
writer.write("你好,世界!");

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

每当有必要将字符编码为二进制数据时(例如,使用InputStreamWriter/OutputStreamWriter类时),如果您不想依赖平台的默认字符集,则应指定一个字符集。如有疑问,请使用Unicode兼容的编码,例如所有Java平台都支持的UTF-8。因此,您可能应该远离此类FileWriter,FileReader因为此类始终使用默认平台字符集。使用字符流访问文件的更好方法是:

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

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

// 从baseReader读取,一次一行
BufferedReader reader = new BufferedReader( baseReader );
String line;
while((line = reader.readLine()) != null) {
  // 切记:System.out是流,不是编写器!
  System.out.println(line);
}