System.in和自定义InputStreamReader之间的行为差​​异

时间:2012-12-05 19:03:28

标签: java polymorphism inputstream bufferedreader

我编写了一个Java CLI程序,它从stdin读取行并为每行输出可能的完成。我试图给它一个gui,所以我试图为System.in构建一个替代品,允许用户使用gui或cli。

到目前为止,我得到了这个替代品,当在JTextArea中输入文本时调用其方法add

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class GuiIn extends InputStream {

    protected LinkedBlockingQueue<Byte> buf;
    protected boolean closed;

    public GuiIn() {
        closed = false;
        buf = new LinkedBlockingQueue<Byte>();
    }

    @Override
    public void close() {
        closed = true;
    }

    /**
     * add strings to read in the InputStream. Arguments are ignored if the
     * stream is closed.
     * 
     * @param s
     *            a string. Ignored if null
     */
    public void add(String s) {
        if (closed || s == null) {
            return;
        }
        byte[] bs = s.getBytes();
        LinkedList<Byte> lbs = new LinkedList<Byte>();
        for (byte b : bs) {
            lbs.add(b);
        }
        buf.addAll(lbs);
    }

    @Override
    public int available() {
        return buf.size();
    }

    @Override
    public synchronized int read() throws InterruptedIOException {
        if (closed && buf.isEmpty()) {
            return -1;
        }
        Byte b = 0;

        while (true) {
            try {

                if ((b = buf.poll(100, TimeUnit.MILLISECONDS)) == null) {
                    if (closed && buf.isEmpty())
                        return -1;
                } else
                    break;

            } catch (InterruptedException e) { 
                throw new InterruptedIOException("interrupted: "
                        + e.getMessage());
            }
        }
        return b;
    }
}

但是,当我尝试使用new BufferedReader(new InputStreamReader(in));并尝试readLine()它时,它似乎会阻塞,直到它有足够的字符(很多),尽管事实上馈送的文本总是附加了听众的换行。

另一方面,如果in设置为System.in,则会在输入后立即读取每一行。

所以,我的问题分为两部分:

  1. 这种差异来自哪里?
  2. 如何解决?
  3. 请注意,从每个字节的裸GuiIn字节读取工作正常,并且我已经尝试过减少BufferedReader缓冲区大小的技巧。

    我之前也在网上搜索过:这不是关于创建一个模拟对象;并且ByteArrayInputStream也不是一个选项:它不支持追加。

1 个答案:

答案 0 :(得分:2)

您的问题的一个来源可能是InputStreamReader可能会坚持提前阅读,以便确保它使用的byte - &gt; char解码器(以及哪些是不透明的)它有足够的字节来产生一个完整的char,而System.in可能已经足够了解默认编码以提供足够的字节。

在开始使用Java的交互式控制台之前,您应该熟悉Console类和readline to Java端口。

然后,我没有指定编码而是创建InputStreamReader,而是在更高层次抽象:

interface CommandLineSource {
  String readLine() throws IOException;
}

然后你可以创建一个由FileDescriptor.STDIN支持的,另一个由你喜欢的,以便你可以自动输入测试。