JAVA BufferedReader 的 mark()、reset() 方法 作者:马育民 • 2023-01-31 10:00 • 阅读:10140 # 介绍 `mark()` 通常与 `reset()` 搭配使用 ## mark() 方法 标记当前位置 [![](/upload/0/0/1IX4sVIik6fO.png)](/upload/0/0/1IX4sVIik6fO.png) 声明: ``` mark(int readlimit) ``` ## reset() 方法 将流重新定位到最近标记的位置 [![](/upload/0/0/1IX4sVJAs7DS.png)](/upload/0/0/1IX4sVJAs7DS.png) [![](/upload/0/0/1IX4sVJaO3OV.png)](/upload/0/0/1IX4sVJaO3OV.png) 声明: ``` reset() ``` # 例子 ### 文件 准备 `1.txt` 文件,内容如下: ``` 李雷 韩梅梅 lucy lili ``` ### 类 ``` package std1; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; public class Buffered的MarkReset方法 { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("1.txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); // 读取第一行 String line = br.readLine(); System.out.println(line); // 读取第一行后,进行 mark() 标记,标记在第二行开始位置 韩梅梅 br.mark(0); // 读取第二行 line = br.readLine(); System.out.println(line); // 读取第三行 line = br.readLine(); System.out.println(line); // 重置后,定位到上一次标记的位置,即:第二行开始位置 br.reset(); // 又从第二行开始位置读取 line = br.readLine(); System.out.println(line); br.close(); isr.close(); fis.close(); } } ``` ### 执行结果 ``` 李雷 // 读取第一行后,进行 mark() 标记,标记在第一行结束位置 韩梅梅 lucy // 读取第三行后,进行 reset() 重置,定位到第一行结束位置 韩梅梅 // 再次读取时,从第二行开始读取 ``` # mark() 参数 保证在 `mark` 以后最多可以读取 `readlimit` 字节数据,`mark` 标记仍有效。 如果在 `mark` 后读取 **超过** `readlimit` 字节数据,`mark` 标记就会失效,调用 `reset()` 方法会有异常。 ### 实际情况 从上面例子可知,调用 `mark(int readlimit)` 方法,`readlimit` 参数未 `0`,读取超过 `readlimit` 字节的数据,`mark` 标记仍有效,仍然能正确调用 `reset()` 方法重置。 **注意:**从上面例子,可能读取到某个位置就会报错,也可能不报错 ### 原因 `mark()` 方法和缓冲区相关。**只要缓冲区够大**,`mark` 后读取的数据没有超出缓冲区的大小,`mark` 标记就不会失效。如果不够大,`mark` 后又读取了大量的数据,导致缓冲区更新,原来标记的位置自然找不到了。 因此,`mark` 后读取多少字节才失效,并不完全由 `readlimit` 参数确定,也和 **缓冲区大小有关**。 #### 例子-报错 ``` package std1; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; public class Buffered的MarkReset报错 { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("1.txt"); InputStreamReader isr = new InputStreamReader(fis); // 缓冲区设置为8个字符 BufferedReader br = new BufferedReader(isr,8); // 读取第一行 String line = br.readLine(); System.out.println(line); // 读取第一行后,进行标记 br.mark(0); // 读取第二行 line = br.readLine(); System.out.println(line); // 读取第三行 line = br.readLine(); System.out.println(line); // 重置 br.reset(); // 重置后,定位到上一次标记的位置,开始继续读取 // 所以又读取到第二行 line = br.readLine(); System.out.println(line); br.close(); isr.close(); fis.close(); } } ``` ### 如何设置才保证不报错 是否报错,与 **缓冲区大小**,文件大小、`readlimit` 的大小有关,为了确保不报错,可以简单设置 `readlimit` 值为 `文件大小+1` #### 例子-一定不报错 ``` package std1; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; public class Buffered的MarkReset一定不报错 { public static void main(String[] args) throws Exception { File file = new File("1.txt"); FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis); // 缓冲区设置为8个字符 BufferedReader br = new BufferedReader(isr,8); // 读取第一行 String line = br.readLine(); System.out.println(line); // 读取第一行后,进行标记 // 参数是文件大小+1 br.mark((int)file.length()+1); // 读取第二行 line = br.readLine(); System.out.println(line); // 读取第三行 line = br.readLine(); System.out.println(line); // 重置 br.reset(); // 重置后,定位到上一次标记的位置,开始继续读取 // 所以又读取到第二行 line = br.readLine(); System.out.println(line); br.close(); isr.close(); fis.close(); } } ``` 参考: https://blog.csdn.net/liuxiao723846/article/details/117693340 原文出处:http://malaoshi.top/show_1IX4sVu08AZa.html