InputStream, mark(), reset()

16

在下面的代码中,mark()reset() 方法是如何确切地工作的?我尝试编写自己的示例,但它开始引发错误的标记异常或类似的异常,我无法理解在此代码中放置标记和重置方法的意义,因为我看不见这样做与没有的区别。

import java.io.*;

class BufferedInputStreamDemo {
    public static void main(String args[]) {
        String s = "© is a copyright symbol, "
                + "however &copy isn't.\n";
        byte buf[] = s.getBytes();

        ByteArrayInputStream in = new ByteArrayInputStream(buf);
        int c;
        boolean marked = false;

        //try_with_resources
        try (BufferedInputStream f = new BufferedInputStream(in)) {
            while ((c = f.read()) != -1) {
                switch (c) {
                    case '&':
                        if (!marked) {
                            f.mark(32);
                            marked = true;
                        } else {
                            marked = false;
                        }
                        break;
                    case ';':
                        if (marked) {
                            marked = false;
                            System.out.print("(c)");
                        } else
                            System.out.print((char) c);
                        break;
                    case ' ':
                        if (marked) {
                            marked = false;
                            f.reset();
                            System.out.print("&");
                        } else
                            System.out.print((char) c);
                        break;
                    default:
                        if (!marked)
                            System.out.print((char) c);
                        break;
                }
            }
        } catch (IOException e) {
            System.out.println("I/O Error: " + e);
        }
    }
}

2
抛出了什么异常?你有堆栈跟踪吗?请在你的问题上更具体。 - Lion
2
抛出的异常是 I/O Error: java.io.IOException: Resetting to invalid mark,但我写的那个例子里抛出的异常不一样。主要我想问的是在这个例子中 mark(32) 和 reset 方法是做什么用的。 - ashur
@user1165499,请查看我的回答,了解此代码的工作原理以及我在您提供的另一个示例中怀疑的问题所在。 - dan
2个回答

8
当执行f.mark(32);时,读取光标已经在&之后,并且为reset设置了一个标记,以便知道要跳回哪里。因此,当您检测到缺少;来关闭元素时,您需要手动打印&并将读取光标向右移动(在放置标记的&之后,使用mark(32)调用),使用reset方法。在下一次读取时,由于您的marked变量未设置,它将打印字符。 mark(32)表示如果读取光标将超过32个字符,则自动删除标记。这可能是您其他代码中触发错误的原因,因为标记已经无效。

6

请查看API文档:

mark(int)

在此输入流中标记当前位置。随后调用reset方法会将此流重新定位到最后标记的位置,以使后续读取重新读取相同的字节。

readlimit参数告诉此输入流在标记位置失效之前允许读取多少字节。

此方法仅执行in.mark(readlimit)操作。

reset()

重新将此流定位到在此输入流上最后调用标记方法时的位置。
该方法只是执行in.reset()。
流标记旨在用于需要向前读取一些以查看流中内容的情况。通常,这最容易通过调用某个通用解析器来完成。如果流是解析处理的类型,则它会愉快地继续运行。如果流不是该类型,则解析器在失败时应抛出异常。如果这在readlimit字节内发生,则允许外部代码重置流并尝试另一个解析器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接