17
    long end=System.currentTimeMillis()+60*10;
    InputStreamReader fileInputStream=new InputStreamReader(System.in);
    BufferedReader bufferedReader=new BufferedReader(fileInputStream);
    try
    {
        while((System.currentTimeMillis()<end) && (bufferedReader.readLine()!=null))
        {

        }
        bufferedReader.close();
    }
    catch(java.io.IOException e)
    {
        e.printStackTrace();
    }

I actually tried doing the above for reading in 600 miliseconds time after which it should not allow reading but the readline of the bufferedreader is blocking.Please help

pavi
  • 654
  • 1
  • 9
  • 29

5 Answers5

17

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;
        }
    }
}
Mifeet
  • 12,949
  • 5
  • 60
  • 108
  • bufferedReader.readLine could still block your thread. If all the threads in your ThreadPool gets blocked on bufferedReader.readLine() then the caller/consumer of your ThreadPool will eventually get blocked, hence the blocking system – TriCore Jun 29 '18 at 16:56
  • Why do you use `poll` with a timeout though? Since `lines.isEmpty()` fails, this means that lines contain at least one element. Is the timed-based poll really needed here? – insumity Apr 20 '20 at 18:23
  • @insumity Yeah, you may be right there. Unless someone is reading the lines from multiple threads, poll is probably not necessary. – Mifeet Jul 01 '20 at 10:24
  • @Mifeet Thanks so much for the answer. Is there any mirror to the link with the full code available, because the link is dead? – localhost Jan 02 '21 at 08:43
2
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();
    }
}
Chamber
  • 21
  • 2
2

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();
Sibbo
  • 3,796
  • 2
  • 23
  • 41
  • 9
    There is no method called available in BufferedReader but we have ready so I tried with it and got it done.Thank you sibbo. – pavi Oct 24 '11 at 08:42
  • Ok, I forgot, the available() method is implemented by InputStream ;) – Sibbo Oct 24 '11 at 08:48
  • 10
    ready() does not guarantee that a line is ready only that some data is present. readLine() could still block. see http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#ready%28%29 – Martin Serrano Aug 23 '13 at 21:58
  • 7
    This is still blocking!! – TriCore Jun 29 '18 at 16:49
1

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.

Grogi
  • 2,099
  • 17
  • 13
0

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().

Augustus Thoo
  • 492
  • 4
  • 13
  • No actually i just was to read a small quantity data but within specific time interval.I got it done through ready method.Thank you for your suggession. – pavi Oct 24 '11 at 09:12