【发布时间】:2011-01-31 20:06:02
【问题描述】:
有没有办法检查BufferedReader 对象中是否有要阅读的内容?类似于 C++ cin.peek()。谢谢。
【问题讨论】:
-
我感觉 C++ 的窥视和 Java 的窥视有歧义。 “检查是否有要读的东西”与 Java 中的“peek”不匹配。
标签: java bufferedreader peek
有没有办法检查BufferedReader 对象中是否有要阅读的内容?类似于 C++ cin.peek()。谢谢。
【问题讨论】:
标签: java bufferedreader peek
您可以使用PushbackReader。使用它,您可以读取一个字符,然后将其取消读取。这实际上允许您将其推回。
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
【讨论】:
Reader 可能正在返回代码点。您可能会通过截断一个值然后将其推回缓冲区来破坏流。
你可以试试“boolean ready()”方法。 来自 Java 6 API 文档:“如果缓冲区不为空,或者基础字符流已准备好,则缓冲字符流已准备就绪。”
BufferedReader r = new BufferedReader(reader);
if(r.ready())
{
r.read();
}
【讨论】:
以下代码将查看 Stream 中的第一个字节。应该充当你的窥探。
BufferedReader bReader = new BufferedReader(inputStream);
bReader.mark(1);
int byte1 = bReader.read();
bReader.reset();
【讨论】:
如果BufferedReader#readLine() 不返回null,通常的习惯用法是循环检查。如果到达流的结尾(例如文件结尾、套接字关闭等),则返回null。
例如
BufferedReader reader = new BufferedReader(someReaderSource);
String line = null;
while ((line = reader.readLine()) != null) {
// ...
}
如果您不想逐行阅读(这是选择BufferedReader 的主要原因),请改用BufferedReader#ready():
BufferedReader reader = new BufferedReader(someReaderSource);
while (reader.ready()) {
int data = reader.read();
// ...
}
【讨论】:
BufferedReader br = new BufferedReader(reader);
br.mark(1);
int firstByte = br.read();
br.reset();
【讨论】:
您可以使用PushBackReader 读取一个字符,然后将其“推回”。这样您就可以确定某物在那里,而不会影响其整体状态——“窥视”。
【讨论】:
来自 pgmura 的答案(依赖于 ready() 方法)很简单且有效。 但请记住,这是因为 Sun 的方法实现;这并不真正同意文档。如果这种行为很关键,我不会依赖它。 见这里http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4090471 我宁愿选择 PushbackReader 选项。
【讨论】:
我的解决方案是.. 扩展 BufferedReader 并将队列用作 buf,然后您可以在队列中使用 peek 方法。
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;
}
}
}
【讨论】: