how to read from standard input non-blocking?

后端 未结 5 2204
南旧
南旧 2020-12-06 05:25
    long end=System.currentTimeMillis()+60*10;
    InputStreamReader fileInputStream=new InputStreamReader(System.in);
    BufferedReader bufferedReader=new Buffered         


        
相关标签:
5条回答
  • 2020-12-06 05:48
    long end=System.currentTimeMillis()+60*10;
    InputStreamReader fileInputStream = new InputStreamReader(System.in);
    BufferedReader bufferedReader = new BufferedReader(fileInputStream);
    try {
        while ((System.currentTimeMillis() < end)) {
            if (bufferedReader.ready()) {
                System.out.println(bufferedReader.readLine());
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    0 讨论(0)
  • 2020-12-06 05:50

    BufferReader.readLine() can block for a very long time if a line is extremely long like 1M chars.

    Does your file contains such long lines?

    If yes, you may have to break up the lines, or use per-char read methods like BufferReader.read().

    0 讨论(0)
  • 2020-12-06 05:56

    Using BufferedReader.available() as suggested by Sibbo isn't reliable. Documentation of available() states:

    Returns an estimate of the number of bytes that can be read... It is never correct to use the return value of this method to allocate a buffer.

    In other words, you cannot rely on this value, e.g., it can return 0 even if some characters are actually available.

    I did some research and unless you are able to close the process input stream from outside, you need to resort to an asynchronous read from a different thread. You can find an example how to read without blocking line by line here.


    Update: Here is a simplified version of the code from the link above:

    public class NonblockingBufferedReader {
        private final BlockingQueue<String> lines = new LinkedBlockingQueue<String>();
        private volatile boolean closed = false;
        private Thread backgroundReaderThread = null;
    
        public NonblockingBufferedReader(final BufferedReader bufferedReader) {
            backgroundReaderThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        while (!Thread.interrupted()) {
                            String line = bufferedReader.readLine();
                            if (line == null) {
                                break;
                            }
                            lines.add(line);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    } finally {
                        closed = true;
                    }
                }
            });
            backgroundReaderThread.setDaemon(true);
            backgroundReaderThread.start();
        }
    
        public String readLine() throws IOException {
            try {
                return closed && lines.isEmpty() ? null : lines.poll(500L, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                throw new IOException("The BackgroundReaderThread was interrupted!", e);
            }
        }
    
        public void close() {
            if (backgroundReaderThread != null) {
                backgroundReaderThread.interrupt();
                backgroundReaderThread = null;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-06 05:58

    You could check with BufferedReader.available() > 0 if there are chars to read.

    String s;
    
    while((System.currentTimeMillis()<end))
    {
        if (bufferedReader.available() > 0)
            s += bufferedReader.readLine();
    }
    
    bufferedReader.close();
    
    0 讨论(0)
  • 2020-12-06 05:58

    The only reliable way would be to start a worker thread and do the actual reading inside it, while the caller thread would monitor the latency.

    If the worker thread is waiting longer that allowed, the master thread would terminate it and throw an exception.

    0 讨论(0)
提交回复
热议问题