BufferedReader中有什么标记和重置?

sau*_*anu 22 java stream bufferedreader

我想知道有什么mark()reset()方法BufferedReader?我该如何使用它们?我读过Javadoc,但作为初学者,我无法理解它.

Boa*_*ann 15

markreset流的方法提供了一种在流中反向跳转并重新读取数据.

当你打电话mark()BufferedReader它时,它会开始将你从该点读取的数据保存在其内部缓冲区中.当你调用reset()它时会跳回到流的标记位置,因此read()内存缓冲区将满足下一个s.当您阅读该缓冲区的末尾时,它将无缝地返回读取新数据.BufferedInputStream以同样的方式工作.

int参数mark告诉它你希望能够倒退的最大字符数(for BufferedReader)或字节数(for BufferedInputStream).如果您在标记位置之后读取了太多数据,则标记可能会"无效",并且调用reset()将失败并出现异常.

一个小例子:

BufferedReader r = new BufferedReader(new StringReader(
    "Happy Birthday to You!\n" +
    "Happy Birthday, dear " + System.getProperty("user.name") + "!"));
r.mark(1000); // save the data we are about to read
System.out.println(r.readLine()); // read the first line
r.reset(); // jump back to the marked position
r.mark(1000); // start saving the data again
System.out.println(r.readLine()); // read the first line again
System.out.println(r.readLine()); // read the second line
r.reset(); // jump back to the marked position
System.out.println(r.readLine()); // read the first line one final time
Run Code Online (Sandbox Code Playgroud)

在那个例子中,我包含了StringReader一个BufferedReader来获取readLine()方法,但是StringReader已经支持mark并且reset自己了!从一个读操作流在内存中的数据源通常支持markreset自己,因为他们已经有了所有的数据在内存中,所以很容易让他们看了一遍.从文件或管道或网络套接字读取流不自然支持markreset,但你总是可以通过在包装它是功能添加到任何流BufferedInputStreamBufferedReader.


ada*_*ost 9

mark()标记的数据流的特定点和reset()流重置为最新的标记.这些方法提供了一项book-marking功能,允许您在流中预读以检查即将到来的数据.

从这个文件:

标记()方法来标记在输入到该流可以是通过调用reset()方法"复位"的位置.参数readLimit是在标记变为无效之前设置标记后可从流中读取的字符数.例如,如果调用mark()时读取限制为10,那么在调用reset()方法之前从流中读取11个数据字符时,标记无效,并且不需要流对象实例记得那个标记.请注意,此方法可以记住的字符数可能大于内部读缓冲区的大小.它也不依赖于支持标记/重置功能的从属流.


Ant*_*sev 6

Reader::mark(int readLimit) 文件说:

在此阅读器中设置标记位置.参数readLimit指示在标记无效之前可以读取的字符数.如果未超过readLimit,则调用reset()会将阅读器重新定位回标记位置.

例:

import java.io.*;
import static java.lang.System.out;

public class App {

    public static final String TEST_STR = "Line 1\nLine 2\nLine 3\nLine 4\n";

    public static void main(String[] args) {

        try (BufferedReader in = new BufferedReader(new StringReader(TEST_STR))) {

            // first check if this Reader support mark operation
            if (in.markSupported()) {

                out.println(in.readLine());
                in.mark(0);                     // mark 'Line 2'
                out.println(in.readLine());
                out.println(in.readLine());
                in.reset();                     // reset 'Line 2'
                out.println(in.readLine());
                in.reset();                     // reset 'Line 2'
                out.println(in.readLine());
                in.mark(0);                     // mark 'Line 3'
                out.println(in.readLine());
                in.reset();                     // reset 'Line 3'
                out.println(in.readLine());
                out.println(in.readLine());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Line 1
Line 2
Line 3
Line 2
Line 2
Line 3
Line 3
Line 4
Run Code Online (Sandbox Code Playgroud)

  • 从*"为什么示例工作的限制为0(或实际上的任何限制)"*也很容易解释.默认缓冲区大小(在两个示例中都使用)是4096.用于示例的字符串非常小,只要创建了BufferedReader,它就会在第一个缓冲区中完全读取.它不会在以后读取任何内容,因此根本不使用limit参数...使得示例相当无意义并且混淆了恕我直言.稍微更改示例以在BufferedReader构造函数中添加非常小的缓冲区大小(例如2或3)将开始抛出无效标记异常. (14认同)
  • 在运行了我自己的更多示例后,我更了解`mark(readAheadLimit)`/`reset()`机制.基本上,`mark`方法只是标记**当前缓冲区**中的一个点,而`reset`让你回到那个标记点.问题是,它并不意味着在文件或流中标记一个点,因为它需要增加缓冲区大小以保持访问标记点的可能性.这就是为什么一个*应该*使用相对小于缓冲区大小的限制. (2认同)

lza*_*zap 1

阅读器界面不会你返回,你可以直接阅读。另一方面,BufferedReader 创建一个缓冲区,因此您可以在读取时返回一点。这就是这些方法的用途。

使用 mark() 方法,您可以将“标记”放置到某个位置,然后您可以继续阅读。一旦你意识到你想要返回标记的位置,你可以使用reset()来实现。从那时起,您再次读取相同的值。您可以将其用于任何您想要的用途。