根据JAVA官方文档的描述,mark(int readlimit)方法表示,标记当前位置,并保证在mark以后最多可以读取readlimit字节数据,mark标记仍有效。如果在mark后读取超过readlimit字节数据,mark标记就会失效,调用reset()方法会有异常。
但实际的运行情况却和JAVA文档中的描述并不完全相符。 有时候在BufferedInputStream类中调用mark(int readlimit)方法后,即使读取超过readlimit字节的数据,mark标记仍有效,仍然能正确调用reset方法重置。
事实上,mark在JAVA中的实现是和缓冲区相关的。只要缓冲区够大,mark后读取的数据没有超出缓冲区的大小,mark标记就不会失效。如果不够大,mark后又读取了大量的数据,导致缓冲区更新,原来标记的位置自然找不到了。
因此,mark后读取多少字节才失效,并不完全由readlimit参数确定,也和BufferedInputStream类的缓冲区大小有关。 如果BufferedInputStream类的缓冲区大小大于readlimit,在mark以后只有读取超过缓冲区大小的数据,mark标记才会失效。看下面的例子。
<span style= "color: #ff0000;" >ava代码
package packet1;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/** * @author WuDian * */ public class MarkExample {
public static void main(String[] args) {
try {
// 初始化一个字节数组,内有5个字节的数据
byte [] bytes={ 1 , 2 , 3 , 4 , 5 };
// 用一个ByteArrayInputStream来读取这个字节数组
ByteArrayInputStream in= new ByteArrayInputStream(bytes);
// 将ByteArrayInputStream包含在一个BufferedInputStream,并初始化缓冲区大小为2。
BufferedInputStream bis= new BufferedInputStream(in, 2 );
// 读取字节1
System.out.print(bis.read()+ "," );
// 在字节2处做标记,同时设置readlimit参数为1
// 根据JAVA文档mark以后最多只能读取1个字节,否则mark标记失效,但实际运行结果不是这样
System.out.println( "mark" );
bis.mark( 1 );
/*
* 连续读取两个字节,超过了readlimit的大小,mark标记仍有效
*/ // 连续读取两个字节
System.out.print(bis.read()+ "," );
System.out.print(bis.read()+ "," );
// 调用reset方法,未发生异常,说明mark标记仍有效。
// 因为,虽然readlimit参数为1,但是这个BufferedInputStream类的缓冲区大小为2,
// 所以允许读取2字节
System.out.println( "reset" );
bis.reset();
/*
* 连续读取3个字节,超过了缓冲区大小,mark标记失效。
* 在这个例子中BufferedInputStream类的缓冲区大小大于readlimit,
* mark标记由缓冲区大小决定
*/ // reset重置后连续读取3个字节,超过了BufferedInputStream类的缓冲区大小
System.out.print(bis.read()+ "," );
System.out.print(bis.read()+ "," );
System.out.print(bis.read()+ "," );
// 再次调用reset重置,抛出异常,说明mark后读取3个字节,mark标记失效
System.out.println( "reset again" );
bis.reset();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} package packet1;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/** * @author WuDian * */ public class MarkExample {
public static void main(String[] args) {
try {
// 初始化一个字节数组,内有5个字节的数据
byte [] bytes={ 1 , 2 , 3 , 4 , 5 };
// 用一个ByteArrayInputStream来读取这个字节数组
ByteArrayInputStream in= new ByteArrayInputStream(bytes);
// 将ByteArrayInputStream包含在一个BufferedInputStream,并初始化缓冲区大小为2。
BufferedInputStream bis= new BufferedInputStream(in, 2 );
// 读取字节1
System.out.print(bis.read()+ "," );
// 在字节2处做标记,同时设置readlimit参数为1
// 根据JAVA文档mark以后最多只能读取1个字节,否则mark标记失效,但实际运行结果不是这样
System.out.println( "mark" );
bis.mark( 1 );
/*
* 连续读取两个字节,超过了readlimit的大小,mark标记仍有效
*/
// 连续读取两个字节
System.out.print(bis.read()+ "," );
System.out.print(bis.read()+ "," );
// 调用reset方法,未发生异常,说明mark标记仍有效。
// 因为,虽然readlimit参数为1,但是这个BufferedInputStream类的缓冲区大小为2,
// 所以允许读取2字节
System.out.println( "reset" );
bis.reset();
/*
* 连续读取3个字节,超过了缓冲区大小,mark标记失效。
* 在这个例子中BufferedInputStream类的缓冲区大小大于readlimit,
* mark标记由缓冲区大小决定
*/
// reset重置后连续读取3个字节,超过了BufferedInputStream类的缓冲区大小
System.out.print(bis.read()+ "," );
System.out.print(bis.read()+ "," );
System.out.print(bis.read()+ "," );
// 再次调用reset重置,抛出异常,说明mark后读取3个字节,mark标记失效
System.out.println( "reset again" );
bis.reset();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} </span> |
运行结果如下:
Java代码
1,mark
2,3,reset
2,3,4,reset again
java.io.IOException: Resetting to invalid mark
at java.io.BufferedInputStream.reset(BufferedInputStream.java:416)
at packet1.MarkExample.main(MarkExample.java:51)
1,mark
2,3,reset
2,3,4,reset again
java.io.IOException: Resetting to invalid mark
at java.io.BufferedInputStream.reset(BufferedInputStream.java:416)
at packet1.MarkExample.main(MarkExample.java:51) 同样的,在调用mark(int readlimit)方法时,如果readlimit大于BufferedInputStream类缓冲区的大小,缓冲区会被扩大,那mark后最多就可以读readlimit字节。
简言之,BufferedInputStream类调用mark(int readlimit)方法后读取多少字节标记才失效,是取readlimit和BufferedInputStream类的缓冲区大小两者中的最大值,而并非完全由readlimit确定。这个在JAVA文档中是没有提到的。
JAVA中mark()和reset()用法的通俗理解
mark就像书签一样,在这个BufferedReader对应的buffer里作个标记,以后再调用reset时就可以再回到这个mark过的地方。mark方法有个参数,通过这个整型参数,你告诉系统,希望在读出这么多个字符之前,这个mark保持有效。读过这么多字符之后,系统可以使mark不再有效,而你不能觉得奇怪或怪罪它。这跟buffer有关,如果你需要很长的距离,那么系统就必须分配很大的buffer来保持你的mark。
//eg.
//reader is a BufferedReader
reader.mark(50);//要求在50个字符之内,这个mark应该保持有效,系统会保证buffer至少可以存储50个字符
int a = reader.read();//读了一个字符
int b = reader.read();//又读了一个字符
//做了某些处理,发现需要再读一次
reader.reset();
reader.read();//读到的字符和a相同
reader.read();//读到的字符和b相同
相关推荐
Java的I/O操作是Java编程中...以上知识点详细介绍了Java中IO操作的基本概念、流的使用方法、异常处理、缓冲机制等核心内容。Java的IO操作不仅限于文件,还包括网络通信等更广泛的应用场景,是进行Java开发的必备知识。
`mark` 和 `reset` 是Java IO流中的两个关键方法,它们在处理流时提供了重要的功能。这里我们将深入探讨这两个方法的工作原理以及如何在实际编程中应用它们。 `mark(int readlimit)` 方法允许我们在流中设置一个...
这些方法都是用于读取文件的字节流, skip方法用于跳过n个字节,close方法用于关闭流并释放对应的资源,mark和reset方法用于标志当前流读取位置和重置读取指针。 5. OutputStream和InputStream的相似性 ...
* boolean markSupported():测试此输入流是否支持mark和reset方法。 * abstract int read():从输入流中读取数据的下一个字节。 * int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。...
在Java中,有多种方法可以用来识别或检测一个文件或输入流的编码格式。 1. **使用`CharsetDetector`** Java 6引入了`java.nio.charset.CharsetDetector`类,它可以检测输入流的字符编码。以下是一个简单的示例: ...
在Java中,IO流分为两大类:输入流(Input Stream)和输出流(Output Stream),它们分别用于数据的读取和写入。 **File类** File类是Java中用于处理文件和目录的基础类。它提供了平台无关的方法来创建、删除、...
这篇文档主要涵盖了Java输入输出流的基本概念、数据流分类、标准数据流、Java.io包中的数据流和文件类以及文件操作类的方法。 1. 数据流的概念: 流是一种数据处理的概念,分为输入流和输出流。在Java中,流可以...
BufferedReader和BufferedWriter的mark()和reset()方法可以保存当前读写位置,方便回溯;skip()方法可以跳过指定数量的字符或字节。同时,Java IO流的异常处理机制确保了在发生错误时能够及时捕获并处理。 总的来说...
Java还提供了针对文件操作的特殊数据流,如`FileInputStream`和`FileOutputStream`,它们可以直接与文件交互,但不支持`mark()`和`reset()`方法。使用这些类时,可以直接传入文件名来创建实例,从而实现对本地文件的...
`mark()`和`reset()`方法支持标记读取位置,便于回溯。`markSupported()`检查流是否支持标记功能。 2. 字节输出流(Byte Output Stream)的基类是`OutputStream`,例如`FileOutputStream`和`BufferedOutputStream`...
下面详细说明Java NIO中的主要类和方法。 Buffer类(C.1.1): Buffer类是一个抽象类,提供了缓冲区操作的基本结构。以下是一些核心方法的简要说明: - capacity(): 返回此缓冲区的容量。 - clear(): 清除此缓冲区,...
不支持方法 mark()和 reset()。 * 缓冲区数据流有 BufferInputStream 和 BufferOutputStream,它们是在数据流上增加了一个缓冲区,都属于过滤器数据流。 * 读写数据时,数据以块(大小可设置)为单位先进入缓冲区,...
如果支持,可以使用`mark`和`reset`方法来回退到之前标记的位置。 - **`public void reset() throws IOException`**: 将流的位置回退到之前的标记位置。只有当流支持`mark`功能时才能使用此方法。 - **`public...
本文档对 Java 中的输入输出流和文件读写进行了详细的介绍,涵盖了 I/O 类的体系结构、字节流和字符流、InputStream 类的方法等内容,为程序员提供了深入了解 Java 中的输入输出流和文件读写的基础知识。
### Java语言深入文件和流 #### 一、数据流概述 数据流是计算机科学中一个重要的概念,它指的是数据从一处向另一处流动的过程。在Java编程语言中,数据流通常指的是程序与外部设备(如磁盘文件)之间的数据交换...
缓冲流的一个重要特性是可以使用`mark()`和`reset()`方法来标记和重置读取位置。此外,对于输出缓冲流来说,数据会先在内存中缓存,当调用`flush()`方法时,才会将缓存的数据立即写入。 #### 三、类层次结构 Java...
由于`InputStream`类的方法可能抛出`IOException`,所以在实际使用中,通常需要使用try-catch语句进行异常处理,以确保程序的健壮性。 **4. 示例应用** `InputStream`类通常用于从文件、网络、内存或其他数据源...
`mark()`和`reset()`方法支持流的标记和回溯,但并非所有流都支持这些操作,需要通过`markSupported()`检查。 **Reader和Writer** 字符流的基类`Reader`和`Writer`提供类似的方法,但处理的是字符数据。`read()`...
这些概念和方法对于理解和使用Java NIO进行内存数据操作至关重要。 首先,`ByteBuffer`是`Buffer`接口的一个实现,它是用来存储字节数据的缓冲区。`Buffer`家族还包括`CharBuffer`、`IntBuffer`等,分别对应不同的...