如何以最小的延迟扫描慢速InputStream?

时间:2012-11-21 00:01:36

标签: inputstream java.util.scanner java-io

这是一个模拟慢流的模拟InputStream

class SlowInputStream extends InputStream{
    private String internal = "5 6\nNext Line\n";
    private int position = 0;

    @Override
    public int available(){
        if(position==internal.length()) return 0;
        else return 1;
    }

    @Override
    public int read() throws IOException {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new IOException("Sleep Interrupted");
        }
        if(position==internal.length()) return -1;
        return internal.charAt(position++);

    }

}

这是测试代码:

    Scanner s = new Scanner(new SlowInputStream());

    int i=s.nextInt();
    System.out.println("i="+i);
    int j=s.nextInt();
    System.out.println("j="+j);
    s.nextLine();
    String line = s.nextLine();
    System.out.println("line="+line);

    s.close();

上面代码的行为是暂停一段时间并打印三行。什么代码可以输出相同的东西,但分开行之间的等待时间?

2 个答案:

答案 0 :(得分:0)

您还需要覆盖read(byte [],int,int)。你最好不要扩展FilterInoutStream:这就是它的用途。

答案 1 :(得分:-1)

如果从Scanner创建InputStream,则会尝试每次都读取特定数量的数据,以提高效果。在我的机器中,金额为4096字节。这就是为什么在这个例子中它始终保持等待直到同时打印所有结果。

要绕过此缓存机制,应使用接口Readable而不是原始流。因为没有已知的实现可以这样做,所以必须实现自己的实现。 (如果有人知道这样的事情,请告诉我)所以下面的代码可以完成这项工作:

Scanner s = new Scanner(new Readable(){

    private InputStream is = new SlowInputStream();

    public int read(CharBuffer arg0) throws IOException {
        int i = is.read();
        if(i>=0){
            arg0.append((char)i);
            return 1;
        } else return -1;
    }

});

int i=s.nextInt();
System.out.println("i="+i);
int j=s.nextInt();
System.out.println("j="+j);
s.nextLine();
String line = s.nextLine();
System.out.println("line="+line);

s.close();
编辑:上述解决方案有一些缺点。首先,它不会关闭内部输入流,因此存在泄漏。其次,它取决于charset是单字节。它不适用于多字节字符集(即UTF-8)。要解决这些问题,我们可以改为使用ReadableByteChannel

Scanner s = new Scanner(new ReadableByteChannel(){

    private InputStream is = new SlowInputStream();
    boolean isopen = true;

    public int read(ByteBuffer arg0) throws IOException {
        int i = is.read();
        if(i>=0){
            arg0.put((byte)i);
            return 1;
        } else return -1;
    }

    public void close() throws IOException {
        isopen=false;
        is.close();
    }

    public boolean isOpen() {
        return isopen;
    }

});
编辑:感谢您的评论,我已修复了文本中的错误,并对此问题给出了更好的解释。