我想知道mark()
的{{1}}和reset()
方法是什么?我该如何使用它们?我读过Javadoc,但作为初学者,我无法理解它。
答案 0 :(得分:14)
流的mark
和reset
方法提供了一种在流中向后跳转并重新读取数据的方法。
当你在mark()
上拨打BufferedReader
时,它会开始将你从该点读取的数据保存在其内部缓冲区中。当您调用reset()
时,它将跳回到流的标记位置,因此内存缓冲区将满足下一个read()
。当您阅读该缓冲区的末尾时,它将无缝地返回读取新数据。 BufferedInputStream
的工作方式相同。
mark
的int参数告诉它您希望能够倒退的最大字符数(对于BufferedReader
)或字节(对于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
在该示例中,我将StringReader
包裹在BufferedReader
中以获取readLine()
方法,但StringReader
已支持mark
和{{1} }} 他们自己!从内存中数据源读取的流通常支持reset
和mark
,因为它们已经拥有内存中的所有数据,因此它们很容易读取再次。从文件或管道或网络套接字读取的流自然不支持reset
和mark
,但您始终可以将该功能包装到reset
或{{1 }}
答案 1 :(得分:9)
mark()
标记流中的特定点,reset()
将流重置为最新标记。这些方法提供book-marking
功能,允许您在流中预读以检查即将到来的数据。
标记()方法标记输入中可以“重置”流的位置 调用reset()方法。参数readLimit是数字 在之前设置标记后可以从流中读取的字符 商标无效。例如,如果使用read调用mark() 限制为10,然后从流中读取11个数据字符 在调用reset()方法之前,那么标记是无效的 流对象实例不需要记住标记。注意 可以通过此方法记住的字符数 大于内部读缓冲区的大小。它也不是 依赖于支持标记/重置的从属流 功能。
答案 2 :(得分:6)
Reader::mark(int readLimit)
文档说:
在此阅读器中设置标记位置。参数 readLimit表示 在标记无效之前可以读取多少个字符。 调用reset()会将阅读器重新定位回标记位置 如果没有超越readLimit。
示例:
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();
}
}
}
输出:
Line 1
Line 2
Line 3
Line 2
Line 2
Line 3
Line 3
Line 4
答案 3 :(得分:1)
读者界面不让你回来,你可以阅读。另一方面,BufferedReader创建一个缓冲区,因此您可以在读取时返回一点。这就是这些方法的用途。
使用mark()方法,您可以在某个位置放置“标记”,然后您可以继续阅读。一旦你意识到你想要返回标记的位置,你就可以使用reset()。从那时起,您再次阅读相同的值。你可以将它用于任何你想要的东西。
答案 4 :(得分:1)
想象一下,你在BufferReader =“123456789”中有以下字符,如果你在相对于'5'字符的位置4标记,那么重置你的BufferReader,你最终会得到12345。
答案 5 :(得分:0)
这是一个例子。
int bufferSize = 4;
int readLimit = 4
ByteArrayInputStream byteInputStream = new ByteArrayInputStream("123456789abcdef".getBytes());
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(byteInputStream, bufferSize)) {
bufferedInputStream.mark(readLimit);
System.out.print((char) bufferedInputStream.read());//byte1
System.out.print((char) bufferedInputStream.read());//byte2
System.out.print((char) bufferedInputStream.read());//byte3
System.out.print((char) bufferedInputStream.read());//byte4
bufferedInputStream.reset();
System.out.print((char) bufferedInputStream.read());//byte5
// Using this next reset() instead of the first one will throw an exception
// bufferedInputStream.reset();
System.out.print((char) bufferedInputStream.read());
System.out.print((char) bufferedInputStream.read());
System.out.print((char) bufferedInputStream.read());
}
输出:12341234
出于readLimit
的目的,here's是一个很好的参考。