【问题标题】:How to return to the beginning of a Bufferedreader?如何返回到 Bufferedreader 的开头?
【发布时间】:2015-05-07 11:17:46
【问题描述】:

这是我的代码:

public int Part1(BufferedReader reader) throws IOException{
        reader.mark(0);
        int counter1 = 0;
        String z;
        while((z = reader.readLine()) != null){
            counter1 = counter1 + z.length();
        }
        reader.reset();   // this is the error line
        return counter1;
    }

这是一个计算文件中字符数的代码。我有其他算法可以在同一个程序中运行,它需要 BufferedReader 返回到文件的开头。我查看了 StackOverFlow 上的另一个答案,并尝试使用 mark() 和 reset() 方法。但是,有一个运行时错误:

线程“main”java.io.IOException 中的异常:未标记流 在 java.io.BufferedReader.reset(未知来源)

这里有什么问题?

【问题讨论】:

  • 你不能。流只会前进。关闭并重新打开文件。

标签: java bufferedreader reset


【解决方案1】:

mark() 的文档中,您传递给它的参数是:

readAheadLimit - 限制在保留标记的同时可以读取的字符数。在读取达到此限制或超过此限制的字符后尝试重置流可能会失败。大于输入缓冲区大小的限制值将导致分配一个大小不小于限制的新缓冲区。因此,应谨慎使用较大的值。

你已经通过了 0;因此,您已经告诉它在读取 0 个字符区域后使标记无效,这基本上是立即的。

您的选择:

  • 您可以传递文件大小,但请注意有关大值的警告。

  • 重新打开文件并为每个方法使用新的Readers 重新开始(您可以将文件名传递给方法并让它们处理,或者在更高级别重新打开它并传递每种方法都有闪亮的新BufferedReader)。

  • 改用FileChannel及其定位方法。

  • 改用RandomAccessFile 及其查找方法。

  • 切换到InputStreams 而不是Readers(注意你的字符编码),如果底层流是FileInputStream,你可以使用它的通道接口重置到开头,例如:

    FileInputStream fileStream = ...; // once when you open the file
    
    // For each method (us-ascii as example):
    fileStream.getChannel().position(0);
    BufferedReader reader = new BufferedReader(new InputStreamReader(fileStream, "us-ascii"));
    // Use reader only in that method, resetting as above for each.
    

【讨论】:

    【解决方案2】:

    另一种选择是在下次需要时声明另一个 BufferedReader,而不是不断重置同一个 BufferedReader。

    【讨论】:

    • 如果你只这样做,第二个BufferedReader 将大致从第一个停止的地方开始。
    【解决方案3】:

    我建议不要重置阅读器,因为阅读器可以坐在另一个阅读器或流或文件上,也必须重置才能工作。这会导致很多问题。尝试同时做这两件事或打开另一个 BufferedReader 但确保它下面的流和阅读器也是新鲜的。

    当你从一个文件中读取时,你可能不会通过重置它来获得任何东西。可能就像创建一个新的阅读器一样工作。

    【讨论】:

    • 仅供参考,BufferedReader 不会调用底层流重置。相反,它使用mark()readAheadLimit 参数将输入缓冲区的大小调整为在标记时间足够大,然后填充它,而不使用任何支持流的重置。这就是如果自标记以来已读取超过readAheadLimit 字节的标记无效的原因。不过,不使用阅读器的建议仍然是一个好建议,但原因不同。
    • 感谢您的反馈。检查了代码。因此,避免重置任何内容的原因主要是这两个代码 cmets:“对 reset() 的后续调用 将尝试将流重新定位到这一点......因此 大值应该与关心。”所以根本没有什么邀请我们使用这个功能。
    • 是的,总的来说,标记/重置机制对我来说似乎很可疑,(而且支持很差——甚至FileReader 都没有实现它)。我想这是 nio 改用SeekableByteChannel 接口方法的原因之一。
    【解决方案4】:

    BufferedReader 移动光标是没用的... 又一个表面上Java的utils(而不是Fortran和Python更简陋的编程语言),你必须使用:

    RandomAccessFile randomAccessFile =new RandomAccessFile(filePath, "rw");
    

    并使用randomAccessFile.seek(0);

    将光标移到起始位置,也是您喜欢的。见:Read lines of characters and get file position

    【讨论】:

      猜你喜欢
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      • 2018-12-11
      • 2014-12-09
      • 2013-10-11
      • 2015-12-13
      • 2022-09-22
      相关资源
      最近更新 更多