Is there a way to check if in BufferedReader
object is something to read? Something like C++ cin.peek()
. Thanks.

- 26,356
- 27
- 122
- 180

- 23,727
- 30
- 106
- 194
-
2I have the feeling that there is ambiguity in C++'s peek and Java's peek. "check if there is something to read" doesn't match with "peek" in Java. – BalusC Mar 25 '10 at 17:09
8 Answers
You can use a PushbackReader. Using that you can read a character, then unread it. This essentially allows you to push it back.
PushbackReader pr = new PushbackReader(reader);
char c = (char)pr.read();
// do something to look at c
pr.unread((int)c); //pushes the character back into the buffer

- 17,731
- 7
- 58
- 97

- 10,274
- 3
- 35
- 42
-
2
-
Your `Reader` may be returning code points. You're potentially corrupting the stream by truncating a value and then pushing it back into the buffer. – Zhro Mar 17 '20 at 02:46
-
Can you please tell us will the data be pushed at the end of the stream or at the start. Just confirming because I feel creating something like unread which pushes character at the end of the buffer will corrupt data so there is no need to create something like that. – Umar Tahir Dec 02 '20 at 15:30
You can try the "boolean ready()" method. From the Java 6 API doc: "A buffered character stream is ready if the buffer is not empty, or if the underlying character stream is ready."
BufferedReader r = new BufferedReader(reader);
if(r.ready())
{
r.read();
}

- 708
- 5
- 16
The following code will look at the first byte in the Stream. Should act as a peek for you.
BufferedReader bReader = new BufferedReader(inputStream);
bReader.mark(1);
int byte1 = bReader.read();
bReader.reset();

- 25,001
- 7
- 80
- 118
-
-
Yes I do want a int peek(). If there is something in a stream I'll get the answer to that by checking return value but state of the stream wont change. – There is nothing we can do Mar 26 '10 at 09:09
-
1@Thereisnothingwecando (I know, 7yrs old... but for others who read this...) His answer is a real peek equivalent. You actually could make a class that extends BufferedReader and just add the method peek() with those 3 lines. Voila – Daidon Jan 12 '17 at 02:52
The normal idiom is to check in a loop if BufferedReader#readLine()
doesn't return null
. If end of stream is reached (e.g. end of file, socket closed, etc), then it returns null
.
E.g.
BufferedReader reader = new BufferedReader(someReaderSource);
String line = null;
while ((line = reader.readLine()) != null) {
// ...
}
If you don't want to read in lines (which is by the way the major reason a BufferedReader
is been chosen), then use BufferedReader#ready()
instead:
BufferedReader reader = new BufferedReader(someReaderSource);
while (reader.ready()) {
int data = reader.read();
// ...
}

- 1,082,665
- 372
- 3,610
- 3,555
BufferedReader br = new BufferedReader(reader);
br.mark(1);
int firstByte = br.read();
br.reset();

- 51,004
- 28
- 112
- 141
You could use a PushBackReader
to read a character, and then "push it back". That way you know for sure that something was there, without affecting its overall state - a "peek".

- 398,947
- 96
- 818
- 769
-
how does pushbackreader works, I am guessing it will push data at the start of buffer reading which will maintain overall state of message thus avoiding packet to get corrupted – Umar Tahir Dec 02 '20 at 15:31
The answer from pgmura (relying on the ready() method) is simple and works. But bear in mind that it's because Sun's implementation of the method; which does not really agree with the documentation. I would not rely on that, if this behaviour is critical. See here http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4090471 I'd rather go with the PushbackReader option.

- 73,180
- 20
- 142
- 190
my solution was.. extending BufferedReader and use queue as buf, then you can use peek method in queue.
public class PeekBufferedReader extends BufferedReader{
private Queue<String> buf;
private int bufSize;
public PeekBufferedReader(Reader reader, int bufSize) throws IOException {
super(reader);
this.bufSize = bufSize;
buf = Queues.newArrayBlockingQueue(bufSize);
}
/**
* readAheadLimit is set to 1048576. Line which has length over readAheadLimit
* will cause IOException.
* @throws IOException
**/
//public String peekLine() throws IOException {
// super.mark(1048576);
// String peekedLine = super.readLine();
// super.reset();
// return peekedLine;
//}
/**
* This method can be implemented by mark and reset methods. But performance of
* this implementation is better ( about 2times) than using mark and reset
**/
public String peekLine() throws IOException {
if (buf.isEmpty()) {
while (buf.size() < bufSize) {
String readLine = super.readLine();
if (readLine == null) {
break;
} else {
buf.add(readLine);
}
}
} else {
return buf.peek();
}
if (buf.isEmpty()) {
return null;
} else {
return buf.peek();
}
}
public String readLine() throws IOException {
if (buf.isEmpty()) {
while (buf.size() < bufSize) {
String readLine = super.readLine();
if (readLine == null) {
break;
} else {
buf.add(readLine);
}
}
} else {
return buf.poll();
}
if (buf.isEmpty()) {
return null;
} else {
return buf.poll();
}
}
public boolean isEmpty() throws IOException {
if (buf.isEmpty()) {
while (buf.size() < bufSize) {
String readLine = super.readLine();
if (readLine == null) {
break;
} else {
buf.add(readLine);
}
}
} else {
return false;
}
if (buf.isEmpty()) {
return true;
} else {
return false;
}
}
}

- 11
- 3
-
1The idea behind your solution is quite smart, but I think we do not need to extend BufferStreamReader rather use a queue and put your bytes into it while peeking into to get the size of the packet or do processing related to your protocol. It will be kind of having your own buffer :) – Umar Tahir Dec 02 '20 at 15:48