Updated Question (to be more clear):
Is there a way to design the InputStream below such that BufferedReader#readLine()
will return after reading the new line character?
In the example below, readLine()
hangs forever even though the reader has read a new line because (presumably) it is waiting for the buffer to fill up. Ideally, readLine()
would return after reading the new line character.
I know something like what I want is possible, because when you read from System.in
using BufferedReader#readLine()
, it does not wait for the buffer to fill up before returning.
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());
}
}
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 PipedInputStream
instead. I've coupled it to a PipedOutputStream
, and BufferedReader#readLine()
returns immediately as long as I call PipedOutputStream#flush()
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
System.out.println(in.readLine());
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.
Also, if there is a better way to send a string to an InputStream, I'm open to suggestions.
Well, instead of an InputStream
you can try a BufferedReader
, with something that looks like this:
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);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.