根据Java documentation,类InputStream服务器中mark方法的 readlimit 参数用于set “在标记位置变为可读之前的最大字节数限制无效“。。 我有一个名为 sample.txt 的文件,其内容为“hello”。我写了这段代码:
import java.io.*;
public class InputStream{
public static void main (String[] args) throws IOException {
InputStream reader = new FileInputStream("sample.txt");
BufferedInputStream bis = new BufferedInputStream(reader);
bis.mark(1);
bis.read();
bis.read();
bis.read();
bis.read();
bis.reset();
System.out.println((char)bis.read());
}
}
输出为“h”。但如果我在标记方法之后读取多个字节,那么我是否应该为无效的重置方法调用收到错误?
答案 0 :(得分:5)
我会将此归结为文档错误。
BufferedInputStream
的非参数文档是“查看InputStream标记方法的常规合同”,这对我来说表明BufferedInputStream
的行为不同,尽管参数文档也是如此。
由InputStream
指定的一般合同是
readlimit参数告诉此输入流允许在标记位置无效之前读取多个字节[...]如果从流中读取超过readlimit字节,则根本不需要记住任何数据流
换句话说,readlimit
是一个建议;流可以免于承诺和过度交付。
答案 1 :(得分:2)
如果你看一下source,特别是fill()方法,你可以看到(过了一会儿!),它只会在必要时使标记无效,即它比文件更宽容可能会暗示。
...
else if (pos >= buffer.length) /* no room left in buffer */
if (markpos > 0) { /* can throw away early part of the buffer */
int sz = pos - markpos;
System.arraycopy(buffer, markpos, buffer, 0, sz);
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
....
默认缓冲区大小相对较大(8K),因此在您的示例中不会触发失效。
答案 2 :(得分:1)
查看BufferedInputStream
的实现,它描述了JavaDocs(受保护的markpos
字段)中标记位置的重要性:
[
markpos
是]调用上一个pos
方法时mark
字段的值。此值始终在
-1
到pos
的范围内。如果输入流中没有标记位置,则此字段为-1
。如果输入流中存在标记位置,则buf[markpos]
是在reset
操作之后作为输入提供的第一个字节。如果markpos
不是-1
,则位置buf[markpos]
到buf[pos-1]
的所有字节都必须保留在缓冲区数组中(尽管它们可能会移动到缓冲区数组中的另一个位置,适当调整count
,pos
和markpos
)的值;除非pos
和markpos
之间的差异超过marklimit
,否则不得丢弃它们。
希望这会有所帮助。查看课程中read
,reset
和私有方法fill
的定义,看看它们是如何结合在一起的。
简而言之,只有当类检索更多数据以填充其缓冲区时,才会考虑标记位置。如果读取的字节数多于允许的mark
调用,则会正确无效。因此,对read
的调用不一定会触发公共JavaDoc注释中公布的行为。
答案 3 :(得分:1)
这看起来像一个微妙的错误。如果减小缓冲区大小,则会得到IOException
public static void main(String[] args) throws IOException {
InputStream reader = new ByteArrayInputStream(new byte[]{1, 2, 3, 4, 5, 6, 7, 8});
BufferedInputStream bis = new BufferedInputStream(reader, 3);
bis.mark(1);
bis.read();
bis.read();
bis.read();
bis.read();
bis.reset();
System.out.println((char)bis.read());
}