java.io.IOException: 标记无效

java.io.IOException: Mark invalid

public void createNewUser(String name, String passwort) {
        try {
            br = new BufferedReader(new FileReader("Data.txt"));
        } catch (FileNotFoundException brCreateError) {
            brCreateError.printStackTrace();
        }

        try {
            br.mark(1);
            System.out.println(br.readLine());
            try {
                if(br.readLine()==null) {
                    noUser=true;
                }else {
                    noUser=false;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            br.reset();

        } catch (IOException brMarkError) {
            brMarkError.printStackTrace();
        } ...

为什么通过 if 语句后 markedChar 值变为 -2?

感谢 Nico 的每一个回答。

public void mark(int readAheadLimit)
      throws IOException

Marks the present position in the stream. Subsequent calls to reset() will attempt to reposition the stream to this point.

...

Parameters:

readAheadLimit- Limit on the number of characters that may be read while still preserving the mark. An attempt to reset the stream after reading characters up to this limit or beyond may fail. A limit value larger than the size of the input buffer will cause a new buffer to be allocated whose size is no smaller than limit. Therefore large values should be used with care.

您将 readAheadLimit 设置为 1 个字符,然后阅读整行。这使标记无效。

我对那个该死的异常有同样的问题:Mark Invalid.

我来到这个论坛,但没有找到有用的东西,所以我不得不自己弄清楚会发生什么。

从我调用 BufferedReader :: mark (int readAheadLimit) 函数的那一刻起,BufferedReader 创建了一个缓冲区(谁会这么说),字符(非行)缓冲区的大小由 readAheadLimit 给出。

一旦超过这个限制,就不能再用BufferedReader::reset()返回了,在标记的时候,因为虽然buffer的第一个数据可以恢复,但是后面的(后面的)缓冲区大小的最大值和当前文件位置之前)将无法检索它们。

为了避免错误,通过将标记设置为 -2 使标记无效,并且在调用重置时会产生异常:Mark Invalid.问题是 BufferedReader 不可能,去返回读取文件的指针,它是通过将数据存储在内存(缓冲区)中来模拟的。

所以如果你运行进入一个Invalid Mark异常,你应该在调用mark(int)方法时把缓冲区变大

为此,我们需要了解 BufferedReader 的工作原理...

BufferReader 将一次读取 8192 个字符并将其存储在字符缓冲区 - cb(可以更改默认值)。

readLine() - 将尝试从字符缓冲区获取数据,如果它需要的字符多于可用字符,它将再次获取并填充接下来的8192个字符...

mark() - 用于创建当前行,因此使用 reset() 方法我们可以回到之前标记的行。

mark()方法接受一个参数——readAheadLimit,应该是最大值该行中的字符数。

如 Java 文档中所述 - 限制小于行大小 可能 失败。 https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#mark(int)

If we try to fill the character array again after the character buffer array is exhausted and the number of pending characters is more than the marked limit (readAheadLimit). It will mark the markedChar as INVALIDATED. The next call to reset will lead to IOException - Mark invalid

结论:

确保 readAheadLimit 是一行中可以出现的最大字符数。

如果该行已经填充到字符缓冲区中,您将不会收到任何错误,因为检查是在尝试再次填充字符缓冲区时完成的。

这就是 may fail 在 Java 文档中的意义。