问题 InputStream,mark(),reset()


如何 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);
        }
    }
}

9796
2017-11-02 14:01


起源

什么例外被抛出?你有堆栈跟踪吗?请更具体地说明您的问题。 - Lion
抛出的异常是 I/O Error: java.io.IOException: Resetting to invalid mark,但我写了另一个例子中引发了异常。主要是我问什么是标记(32)和重置做什么 这个例子。 - ashur
@ user1165499在你的另一个例子中,请参阅我的答案,详细了解此代码的工作原理以及我怀疑的问题。 - dan


答案:


什么时候 f.mark(32); 到达后读取光标已经到了 &,并设置标记 reset 知道在哪里跳回来。所以,当你检测到一个 ; 缺少关闭元素,您手动打印 & 并将读取光标向后移动(之后 & 使用标记放置标记的位置 mark(32) 打电话),使用 reset 方法。在下一次阅读,因为你的 marked 变量未设置它将打印字符。

mark(32) 意味着如果您的读取光标将超过32个字符,则自动删除标记。这可能是您的其他代码中的问题,即触发错误,因为标记已经失效。


6
2017-11-02 14:15





请参阅API文档:

mark(int)

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

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

此方法只执行in.mark(readlimit)。

reset()

将此流重新定位到上次在此输入流上调用mark方法时的位置。

此方法只执行in.reset()。

流标记旨在用于需要提前阅读以查看流中的内容的情况。通常,这通过调用一些通用解析器最容易完成。如果流是由解析处理的类型,那么它只是愉快地开始。如果流不是该类型,则解析器在失败时应该抛出异常。如果这发生在readlimit字节内,它允许外部代码重置流并尝试另一个解析器。


4
2017-11-02 14:07