【问题标题】:BufferedInputStream.mark() method not working as expectedBufferedInputStream.mark() 方法未按预期工作
【发布时间】:2020-07-25 08:43:23
【问题描述】:

代码:

import java.io.*;
public class BufferedInputStreamDemo {
    public static void main(String[] args) throws IOException {
        String phrase = "Hello World #This_Is_Comment# #This is not comment#";
        byte[] bytes = phrase.getBytes();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        BufferedInputStream bin = new BufferedInputStream(in);
        int character;
        boolean com = false;
        while ((character = bin.read()) != -1) {
            switch(character) {
                case '#' :
                    if (com) com = false;
                    else {
                        com = true;
                        bin.mark(1000);
                    }
                    break;
                case ' ' :
                    if (com) {
                        com = false;
                        System.out.print('#');
                        bin.reset();
                    }
                    else  {
                        System.out.print((char)character);
                    }
                    break;
                default : if (!com) System.out.print((char)character);
            }
        }
        in.close(); bin.close();

    }
}

这段代码有什么作用?

此代码读取字符串,bufferStream 删除/隐藏 cmets。这里的 cmets 用 #this_is_comment# 表示,带有 ' ' (空格)的 cmets 不被视为注释 ex : #这不是评论#。

问题:

每当遇到''(空格)并且 com(布尔值,当 true 不读取流)为 true 时,它​​会将流恢复到标记的位置,我怀疑如果它恢复,# 不是再次遇到并且 com 将被设置为 false 因此考虑它的评论。

case '#' :
        if (com) com = false;
        else {
            com = true;
            bin.mark(1000);
        }

但这不是输出正确的情况。

如果可能,请编辑问题以使其更易于理解。

【问题讨论】:

  • 标记的位置是你调用mark()时所处的位置。在这种情况下,您已经阅读了#,因此您的当前位置晚了一个字节。

标签: java bufferedinputstream


【解决方案1】:

这种行为是预期的。如果您阅读了BufferedInputStream 的方法.mark().read() 的实现,您可以看到:

方法.mark()markPos 设置为pos

public synchronized void mark(int readlimit) {
    marklimit = readlimit;
    markpos = pos;
}

问题是pos是谁?只需转到它的定义,就会在 JavaDoc 中找到它(仅报告相关部分):

/**
 * The current position in the buffer. This is the index of the next
 * character to be read from the <code>buf</code> array.
 * <p>
 * ... more JavaDoc
 */
protected int pos;

因此,当您致电 .reset() 时,您正在这样做:

public synchronized void reset() throws IOException {
    getBufIfOpen(); // Cause exception if closed
    if (markpos < 0)
        throw new IOException("Resetting to invalid mark");
    pos = markpos;
}

基本上,您正在恢复流的最后一个“下一个字符”。

为了简单

根据BufferedInputStream的官方JavaDoc,如果您在String s = "Hello World"中并且在读取字符W时调用.mark(),当您执行.reset()时,您将从@987654338之后的下一个字符重新开始@ 即o

这就是为什么您的代码不会再次出现在注释部分的原因。

【讨论】:

猜你喜欢
  • 2019-04-22
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 2020-10-04
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多