繁体   English   中英

BufferedReader#readLine()即使已读取一行也会挂起

[英]BufferedReader#readLine() hangs even though a line has been read

更新的问题(更清楚):

有没有办法在下面设计InputStream,以便在读取新行字符后BufferedReader#readLine()将返回?

在下面的示例中, readLine()永远挂起,即使读者已读取新行,因为(可能)它正在等待缓冲区填满。 理想情况下, readLine()将在读取新行字符后返回。

我知道我想要的东西是可能的,因为当你使用BufferedReader#readLine()System.in读取时,它不会在返回之前等待缓冲区填满。

import java.io.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Example {

    private static final class MyInputStream extends InputStream {

        public final BlockingQueue<String> lines = new LinkedBlockingQueue<>();
        private InputStream current = null;

        @Override
        public int read() throws IOException {
            try {
                if(current == null || current.available() == 0)
                    current = new ByteArrayInputStream(lines.take().getBytes("UTF-8"));
                return current.read();
            }
            catch(InterruptedException ex) {
                return -1;
            }
        }       
    }

    public static void main(String[] args) throws Exception {
        MyInputStream myin = new MyInputStream();
        myin.lines.offer("a line\n");
        BufferedReader in = new BufferedReader(new InputStreamReader(myin));
        System.out.println(in.readLine());
    }
}

此外,如果有更好的方法将字符串发送到InputStream,我愿意接受建议。

接受的解决方案:

根据Sotirios Delimanolis对他的解决方案的评论之一的建议,我将改为使用PipedInputStream 我已将它耦合到PipedOutputStream ,并且只要在发送包含新行字符的字符串后调用PipedOutputStream#flush() BufferedReader#readLine()BufferedReader#readLine()就会立即返回。

在更新问题之后,让新的行字符之后让BufferedReader停止读取的唯一方法是将缓冲区大小设置为1 ,这样就完全不需要BufferedReader

你必须编写自己的实现。


BufferedReader读取的字节数多于所需的字节数。 在您的情况下,这意味着它将比新行字符读取更多。 例如,对于Oracle JVM,它将尝试读取8192个字节。 通过你的继承层次结构,这个

System.out.println(in.readLine());

将尝试调用read()方法8192次。

前6个调用将返回一个值,一个用于String的字节数组中的每个字符。 下一个,将会看到

if(current == null || current.available() == 0)
     current = new ByteArrayInputStream(lines.take().getBytes("UTF-8"));

而且current.available()将返回0,因为ByteArrayInputStream已被完全消耗。 然后,它会尝试takeBlockingQueue和无限期地阻塞。

此外,如果有更好的方法将字符串发送到InputStream,我愿意接受建议。

好吧,您可以尝试使用BufferedReader而不是InputStream ,其内容如下所示:

public int read(String directory) throws Exception{
    String line = "";
    File file = new File(directory);
    FileReader fr = new FileReader(file);
    BufferedReader br = new BufferedReader(fr);

    do{
        lines.add(br.readLine());
    while(br.readLine() != null);

    br.close();

    return Integer.parseInt(line);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM