【问题标题】:Does a bufferedreader wrapped around a file reader gets its file pointer from the filereader?包裹在文件阅读器周围的缓冲阅读器是否从文件阅读器获取其文件指针?
【发布时间】:2018-01-21 08:40:18
【问题描述】:

我有这样的方法:

public void LoadFromFile(){
String record;
try{
        FileReader reader = new FileReader("Friends.txt");  
        BufferedReader bin = new BufferedReader(reader);
        while((record = bin.readLine()) != null){
             //do some stuff
        }
        clientinfo = homeAddress.LoadFromFile(reader);

上面调用的方法homeAddress.LoadFromFile(reader)在另一个类中,如下:

public String[] LoadFromFile(FileReader areader){
String record;
    try{
        BufferedReader bin = new BufferedReader(areader);
        while((record = bin.readLine()) != null){
             //do some stuff
            }
        }
        bin.close();
        bin = null;

我的问题是,我始终使用相同的 FileReader,所以当我将 BufferedReader 包裹在它周围时,BufferedReader 是否使用 FileReader 中的文件指针(从哪里开始读取)?

第一个 BufferedReader 是否更新文件指针,以便第二个 BufferedReader 知道从哪里开始?

【问题讨论】:

  • 你可以做的是传递存储在 bin 中的 bufferedreader,而不是 filereader 对象

标签: java bufferedreader filereader file-pointer


【解决方案1】:

这里的关键是“缓冲”这个词。不,您不能假设第二个LoadFromFile 中的BufferedReader 会准确地接听调用者中的BufferedReader 停止的位置。来自the documentation

从字符输入流中读取文本,缓冲字符以便高效读取字符、数组和行。

(我的重点)

这意味着BufferedReader 将提前读取文件并将该数据保存在其缓冲区中。因此,第二个BufferedReader 将接收第一个未被第一个字符读取的字符——因此您从第一个 BufferedReader 消耗的内容与第二个将消耗的内容之间可能存在差距。

改为:将BufferedReader 传递给第二种方法,相应地更改其签名。

总的来说,它的签名已经有点偏离了。它不需要知道或关心它是从文件还是其他类型的流中读取;它只需要知道它是从BufferedReader 读取的(因为它依赖于readLine)。


旁注:在您的代码中,如果在读取时发生异常,您将没有机会清理读取器分配的非 JVM 资源(特别是 FileReader)。这就是 try-with-resources 真正有用的地方:

try (
    FileReader reader = new FileReader("Friends.txt");  
    BufferedReader bin = new BufferedReader(reader);
) {
    while((record = bin.readLine()) != null){
         //do some stuff
    }
    clientinfo = homeAddress.LoadFromFile(reader);

在那里,即使readLine 发生异常,读取器也会被清除。

【讨论】:

  • 我正在阅读 OP 的问题,他有兴趣从第一个 bufferedreader 停止的地方继续,而不是从头开始,因此即使实施重置也可能无济于事。
  • @eis:嗯,第一个块一直读到最后(直到readLine 返回null),然后才传递给下一个方法,所以我假设他/她会想要从头开始。但这是一个假设,因此可能是错误的。 :-)
  • 我假设// do some stuff 可能包含break。否则这个问题对我来说没有多大意义。
  • @ei 是正确的,调用者中的第一个 BufferedReader 在到达带有文本“###”的行时会中断,我错误地截断了这个问题
  • @ArielKropp:在这种情况下,我在答案的末尾添加了一些内容。
【解决方案2】:

你可以从source code of BufferedReader 看到它有一个内部变量nextChar 用于读取下一个字符的索引,所以除非你自己存储变量或传递 bufferedreader 实例,否则“指针”将不要继续下一次通话。

这很简单,可以测试:

Friends.txt:

foo
bar

代码:

import org.junit.Test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReadingTest {
    @Test
    public void LoadFromFile() throws IOException {
        String record;
        try {
            FileReader reader = new FileReader("Friends.txt");
            BufferedReader bin = new BufferedReader(reader);
            while ((record = bin.readLine()) != null) {
                System.out.println("1: read " + record);
                break;
            }
            LoadFromFile(reader);
        } catch (FileNotFoundException foo) {
            System.out.println("file not found from " + new File(".").getAbsolutePath());
        }
    }
    public void LoadFromFile(FileReader areader) {
        String record;
        try {
            BufferedReader bin = new BufferedReader(areader);
            while ((record = bin.readLine()) != null) {
                System.out.println("2: read " + record);
            }
            bin.close();
            bin = null;
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }
}

执行:

1: read foo

Process finished with exit code 0

所以第二个读者甚至没有机会阅读,即使第一次阅读没有完成。另外,如果在第一次阅读后引入 bin.close(),第二次阅读会抛出java.io.IOException: Stream closed

如 cmets 中所建议的,如果您想继续读取第一个方法停止的第二种方法,最简单的方法是传递相同的缓冲读取器实例。你必须小心在正确的时间释放资源。

【讨论】:

  • 好的,我跟着 - 有没有办法让我停止第一个缓冲阅读器并继续使用第二个缓冲阅读器?
  • @ArielKropp 最简单的方法可能只是传递相同的缓冲读取器实例。另一种选择是将读取的字符数量存储在变量上,完全关闭阅读器,重新打开,并在第一次新读取之前调用 skip skip(amountOfChars)。在我看来,您确实想使用相同的缓冲阅读器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多