sgware sgware - 1 month ago 11
Java Question

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

Updated Question (to be more clear):

Is there a way to design the InputStream below such that

will return after reading the new line character?

In the example below,
hangs forever even though the reader has read a new line because (presumably) it is waiting for the buffer to fill up. Ideally,
would return after reading the new line character.

I know something like what I want is possible, because when you read from
, it does not wait for the buffer to fill up before returning.

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;

public int read() throws IOException {
try {
if(current == null || current.available() == 0)
current = new ByteArrayInputStream(lines.take().getBytes("UTF-8"));
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));

Also, if there is a better way to send a string to an InputStream, I'm open to suggestions.

Accepted Solution:

Based on a suggestion from Sotirios Delimanolis in one of the comments on his solution, I'm just going to used a
instead. I've coupled it to a
, and
returns immediately as long as I call
after sending a string that contains a new line character.


After updated question, the only way to get the BufferedReader to stop reading after the new line character is to set the buffer size to 1, which completely removes the need for a BufferedReader.

You'll have to write your own implementation.

A BufferedReader reads more bytes than required. In your case, that means it will read further than the new line character. For example, with the Oracle JVM, it will attempt to read 8192 bytes. Through your inheritance hierarchy, this


will attempt to invoke your read() method 8192 times.

The first 6 calls will return a value, one for each of the characters in your String's byte array. The next one, will see

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

and current.available() will return 0 since the ByteArrayInputStream has been fully consumed. It will then attempt to take from the BlockingQueue and block indefinitely.