字符流通常是字节流的“包装器”

时间:2019-03-21 19:12:07

标签: java

遍历Java IO Stream中的字符流信息时,发现以下几行很难理解:

字符流通常是字节流的“包装器”。字符流使用字节流执行物理I / O,而字符流则处理字符和字节之间的转换。例如,FileReader使用FileInputStream,而FileWriter使用FileOutputStream。

有人会帮助我理解...谢谢

1 个答案:

答案 0 :(得分:0)

最低级别的文件由字节序列组成。这些字节的含义取决于负责读取和写入这些字节的应用程序。这些字节可以解释为JPEG图像,MP3声音文件或文本。

对于文本解释,您需要字节和字符之间的映射。这些映射称为字符编码。那里有许多不同的字符编码。对于Windows ANSI(Cp1252)或DOS编码(Cp437)之类的简单字符编码,字节和字符之间存在一对一的关系。因此,每个字符都被精确地编码为一个字节。

但是还有更复杂的编码,例如UTF-8。一个字符的字节序列可以由一个字节或两个或多个字节组成。

在Java中,字节级别由字节流类(例如FileInputStreamFileOutputStream)处理。对于字符流(文本),有ReaderWriter的子类。

这两个类InputStreamReaderOutputStreamWriter在这里非常重要,因为它们构成了字符流和字节流之间的连接。

InputStreamReaderReader,因此您可以读取其中的字符。但是它包装了InputStream个字节流。它在内部读取包装的字节流的字节,并根据字符编码将这些字节转换为字符。

OutputStreamWriterWriter。您在其中写入字符或字符串。 OutputStreamWriter包装OutputStream。将字符映射到字节,并将编码写入OutputStream

如果在构造函数中未指定字符编码,则使用平台的默认编码(通常是Windows上的Windows-ANSI和Linux上的UTF-8)。

示例:将字符串Pelé写入UTF-8中的文件name.txt

try(Writer writer = new OutputStreamWriter(new FileOutputStream("names.txt"), StandardCharsets.UTF_8)) {
  writer.write("Pelé");
} catch (IOException e) {
  e.printStackTrace();
}

通常,您添加其他作家,例如用于缓冲或打印:

try(PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
    new FileOutputStream("names.txt"), StandardCharsets.UTF_8)))) {
  writer.println("Pelé");
} catch (IOException e) {
  e.printStackTrace();
}

为完整起见,这是相应的阅读示例。在这里,我们使用Files.newBufferedReader()创建由FileInputStream包裹的BufferedReader

Path namesFile = Paths.get("names.txt");
try(BufferedReader reader = Files.newBufferedReader(namesFile, StandardCharsets.UTF_8)) {
  reader.lines().forEach(System.out::println);
} catch (IOException e) {
  e.printStackTrace();
}