首页 > 解决方案 > 扩展 InputStreamReader 无法正常工作

问题描述

我以这种方式扩展 InputStreamReader

public class AsteriskInputStreamReader extends InputStreamReader {
    boolean ast;
    AsteriskInputStreamReader(InputStream is) {
        super(is);
    }
    @Override
    public int read() throws IOException {
        ast = !ast;
        if (ast) return '*';
        return super.read();
    }
}

它必须在从原始InputStream. 但是当我这样使用它时

InputStreamReader in = new AsteriskInputStreamReader(new FileInputStream("text.txt"));
int c;
while((c = in.read()) != -1){
     System.out.print((char)c);
}

它仅适用于文件中的最后一行。前几行仅输出为一个“*”,没有任何文本。为什么?

第二个问题。

当我BufferedInputStream用它创建并尝试获取文件的第一行时

BufferedReader reader = new BufferedReader(in);
System.out.println(reader.readLine()); 

我得到文件的第一行没有任何'*'。

获得我想要的东西的正确方法是什么:创建包装器InputStreamReader,它将在原始输入的所有符号之后添加星号符号?

标签: javaio

解决方案


而不是子类化InputStreamReader,创建一个单独Reader的,您可以与其他阅读器链接,因此您也可以将其应用于不支持的阅读器InputStream

try (BufferedReader reader = new BufferedReader(
                                new AsteriskReader(
                                   new InputStreamReader(
                                      new FileInputStream("text.txt"))))) {
    // ...
}

格式化以强调链。

它不起作用的原因是BufferedReader它不会调用read()您覆盖的方法,它会调用采用缓冲区(、、或)的read(char[] cbuf)重载read(char[] cbuf, int off, int len)之一read(CharBuffer target)

要实现一个Reader要被链接的子类FilterReader

class AsteriskReader extends FilterReader {
    private boolean ast;
    private boolean astMarked;

    public AsteriskReader(Reader in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        // TODO Add handling of EOF
        ast = !ast;
        if (ast) return '*';
        return super.read();
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        // TODO Implement this, i.e. only read half number of characters from
        //      underlying reader, then inject '*' characters between all the
        //      chars actually read.
        //      Special handling for odd value of len.
        int charsRead = super.read(cbuf, off, len);
        return charsRead;
    }

    @Override
    public long skip(long n) throws IOException {
        // TODO Fix this to handle odd value of n.
        long actualSkipped = super.skip(n / 2);
        return actualSkipped * 2;
    }

    @Override
    public void mark(int readAheadLimit) throws IOException {
        super.mark((readAheadLimit + 1) / 2); // Underlying reader only needs to remember half
        this.astMarked = this.ast;
    }

    @Override
    public void reset() throws IOException {
        super.reset();
        this.ast = this.astMarked;
    }

}

推荐阅读