1. 概述
FileReader
和 BufferedReader
是两个可以从输入流中读取字符的类。
在这个教程中,我们将探讨它们之间的差异。
2. FileReader
FileReader
类可以从文件中读取字符流。 此外,它只能逐个字符读取,每次调用其 read()
方法时,都会直接访问硬盘上的文件,从中读取一个字符。因此,FileReader
在读取文件字符时本身非常慢且效率低下。另外,FileReader
只能读取文件中的字符,不能处理其他类型的输入流。
2.1. 构造函数
FileReader
有三个构造函数:
-
FileReader(File file)
:接收一个File
对象作为参数 -
FileReader(FileDescriptor fd)
:接收一个FileDescriptor
作为参数 -
FileReader(String fileName)
:接收包含路径的文件名作为参数
2.2. 返回值
每次调用 read()
方法,它都会返回一个整数值,表示从文件中读取到的字符的 Unicode 值,如果到达了字符流的末尾,则返回 -1。
2.3. 示例
让我们通过一个例子来了解如何使用 FileReader
从内容为 "qwerty" 的文本文件中读取字符:
@Test
public void whenReadingAFile_thenReadsCharByChar() {
StringBuilder result = new StringBuilder();
try (FileReader fr = new FileReader("src/test/resources/sampleText2.txt")) {
int i = fr.read();
while(i != -1) {
result.append((char)i);
i = fr.read();
}
} catch (IOException e) {
e.printStackTrace();
}
assertEquals("qwerty", result.toString());
}
在上述代码中,我们在将返回值转换为 char
类型后,将其附加到结果字符串上。
3. BufferedReader
BufferedReader
类创建一个缓冲区来存储来自字符输入流的数据。此外,输入流可以是文件、控制台、字符串或其他类型的字符流。
它的构造函数接收一个 Reader
作为字符输入流。因此,我们可以给任何实现了 Reader
抽象类的类提供给 BufferedReader
作为输入流,以便从中读取字符。
当我们开始从 BufferedReader
开始读取时,它会从输入流中读取整个数据块并将其存储在缓冲区中。之后,如果我们继续从 BufferedReader
读取,它将从缓冲区而不是底层字符流返回字符,直到缓冲区为空。然后,它会从输入流中再读取一个数据块,并将其存储在缓冲区中,供后续读取调用。
BufferedReader
类减少了对输入流的读取操作,从缓冲区读取通常比访问底层输入流快得多。因此,BufferedReader
提供了一种更快、更有效的方法来读取字符流。
3.1. 构造函数
BufferedReader
有两个构造函数:
-
BufferedReader(Reader in)
:接收字符输入流(必须实现Reader
抽象类)作为参数 -
BufferedReader(Reader in, int sz)
:接收字符输入流和缓冲区大小作为参数
3.2. 返回值
如果调用 read()
方法,它将返回一个整数值,表示从输入流中读取到的字符的 Unicode 值。如果调用 readLine()
方法,它会从缓冲区中读取一行并以字符串值返回。
3.3. 示例
让我们使用 BufferedReader
和一个 InputStreamReader
实现,从一个包含三行内容的文本文件中读取字符:
@Test
public void whenReadingAFile_thenReadsLineByLine() {
StringBuilder result = new StringBuilder();
final Path filePath = new File("src/test/resources/sampleText1.txt").toPath();
try (BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(filePath), StandardCharsets.UTF_8))) {
String line;
while((line = br.readLine()) != null) {
result.append(line);
result.append('\n');
}
} catch (IOException e) {
e.printStackTrace();
}
assertEquals("first line\nsecond line\nthird line\n", result.toString());
}
这段测试代码成功运行,说明 BufferedReader
成功从文件中读取了所有三行文本。
4. 区别是什么?
BufferedReader
比 FileReader
快且更高效,因为它从输入流中一次性读取整个数据块,并将其保留在缓冲区中供后续读取使用,而 FileReader
需要为每个字符访问文件。此外,FileReader
只能逐字符读取,而 BufferedReader
具有如 readLine()
这样的方法,可以从缓冲区中读取整行。最后,FileReader
只能读取文件,而 BufferedReader
可以读取任何类型的字符输入流(如文件、控制台、字符串等):
FileReader
BufferedReader
较慢且效率较低
更快且更高效
只能逐字符读取
可以读取字符和行
只能读取文件
可以读取任何类型的字符流
对于小文件或文件数据上的读取操作较少的情况,FileReader
可能就足够了。但对于大文件或频繁进行数据读取的操作,BufferedReader
是更好的选择。
5. 总结
在这个教程中,我们学习了如何使用 FileReader
和 BufferedReader
,以及它们之间的差异。
如往常一样,本教程的完整源代码可以在 GitHub 上找到。