包裹在文件阅读器周围的缓冲读取器是否从文件读取器获取其文件指针?

时间:2017-08-13 09:01:29

标签: java bufferedreader filereader file-pointer

我有一个像这样的方法:

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知道从哪里开始?

2 个答案:

答案 0 :(得分:2)

这里的关键是“缓冲”这个词。不,您不能认为第二个BufferedReader中的LoadFromFile会准确到达来电者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中发生异常,也会清理读者。

答案 1 :(得分:0)

你可以从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

正如评论中所建议的那样,如果你想继续阅读第一种方法,那么最简单的方法是传递相同的bufferedreader实例。你必须小心在适当的时候释放资源。