BufferedReader readLine() 块
Posted
技术标签:
【中文标题】BufferedReader readLine() 块【英文标题】:BufferedReader readLine() blocks 【发布时间】:2013-03-09 10:01:43 【问题描述】:当使用 readLine() 接收数据时,即使我在消息末尾放了一个“\n” 发送消息时使用 .flush ,读取我的消息的while循环仍然阻塞。 只有在关闭套接字连接时,才会离开循环。
这是客户端代码:
bos = new BufferedOutputStream(socket.
getOutputStream());
bis = new BufferedInputStream(socket.
getInputStream());
osw = new OutputStreamWriter(bos, "UTF-8");
osw.write(REG_CMD + "\n");
osw.flush();
isr = new InputStreamReader(bis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String response = "";
String line;
while((line = br.readLine()) != null)
response += line;
和服务器的代码:
BufferedInputStream is;
BufferedOutputStream os;
is = new BufferedInputStream(connection.getInputStream());
os = new BufferedOutputStream(connection.getOutputStream());
isr = new InputStreamReader(is);
String query= "";
String line;
while((line = br.readLine()) != null)
query+= line;
String response = executeMyQuery(query);
osw = new OutputStreamWriter(os, "UTF-8");
osw.write(returnCode + "\n");
osw.flush();
我的代码在服务器 while 循环中阻塞。 谢谢。
【问题讨论】:
将代码放入 try/catch 块中,并在 finally 块中关闭流/连接。 这似乎没有问题。您想知道为什么会发生这种行为吗?如何预防? 如果你只想读一行为什么要使用while循环? 【参考方案1】:BufferedReader 将继续读取输入,直到它到达末尾(文件或流或源等的结尾)。在这种情况下,“结束”是套接字的关闭。因此,只要 Socket 连接打开,您的循环就会运行,而 BufferedReader 只会等待更多输入,每次到达 '\n' 时都会循环。
【讨论】:
嗯我不认为结束是套接字的关闭。谢谢。现在我看它,我误读了文档! 当涉及到非文件流的 eof 时,该文档相当模糊。 是 OP 的循环一直读取到 EOS,而不是 BufferedReader。 所以如果连接打开但缓冲区中没有行,它还会循环吗? @the_prole - 循环将继续......有点。它不会退出循环,但br.readLine()
调用将阻塞,直到有新行可用【参考方案2】:
我尝试了很多解决方案,但唯一没有阻止执行的是:
BufferedReader inStream = new BufferedReader(new InputStreamReader(yourInputStream));
String line;
while(inStream.ready() && (line = inStream.readLine()) != null)
System.out.println(line);
如果下一个 readLine()
调用将阻止执行,则 inStream.ready()
返回 false。
【讨论】:
你救了我一个月。我只需要反转inStream.ready()
和 (line = inStream.readLine()) != null
我的 InputStream 是从 java.lang.Process 获得的
@LennoardSilva 是的,我的也是从java.lang.Process
获得的,所以你不会知道什么时候没有什么可以用其他方法阅读了。【参考方案3】:
这是因为while循环中的条件:while((line = br.readLine()) != null)
您在每次迭代时读取一行,如果 readLine 返回null
,则退出循环。
如果达到 eof(= socked 已关闭),readLine 仅返回 null,如果读取了 '\n',则返回一个字符串。
如果你想在 readLine 上退出循环,你可以省略整个 while 循环,直接做:
line = br.readLine()
【讨论】:
【参考方案4】:发生这种情况是因为 InputStream 还没有准备好变红,所以它在 in.readLine() 上阻塞。 请试试这个:
boolean exitCondition= false;
while(!exitCondition)
if(in.ready())
if((line=in.readLine())!=null)
// do whatever you like with the line
当然你要控制exitCondition。
另一个选项可以是使用 nio 包,它允许异步(非阻塞)读取,但这取决于您的需要。
【讨论】:
【参考方案5】:最好避免使用readline()
。这种方法对网络通信很危险,因为有些服务器不返回LF/CR
符号,你的代码就会卡住。当您从文件中读取时,这并不重要,因为无论如何您都会到达文件末尾并且流将被关闭。
public String readResponse(InputStream inStreamFromServer, int timeout) throws Exception
BufferedReader reader = new BufferedReader(new InputStreamReader(inStreamFromServer, Charsets.UTF_8));
char[] buffer = new char[8092];
boolean timeoutNotExceeded;
StringBuilder result = new StringBuilder();
final long startTime = System.nanoTime();
while ((timeoutNotExceeded = (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) < timeout)))
if (reader.ready())
int charsRead = reader.read(buffer);
if (charsRead == -1)
break;
result.append(buffer, 0, charsRead);
else
try
Thread.sleep(timeout / 200);
catch (InterruptedException ex)
LOG.error("InterruptedException ex=", ex);
if (!timeoutNotExceeded) throw new SocketTimeoutException("Command timeout limit was exceeded: " + timeout);
return result.toString();
它有一个超时,如果需要很长时间你可以中断通信
【讨论】:
您必须确定您使用的协议。大多数协议都指定了它们的行尾行为。【参考方案6】:如果您想在不强制关闭它的情况下获取套接字中的内容,只需使用 ObjectInputStream 和 ObjectOutputStream ..
示例:
ObjectInputStream ois;
ObjectOutputStream oos;
ois = new ObjectInputStream(connection.getInputStream());
String dataIn = ois.readUTF(); //or dataIn = (String)ois.readObject();
oos = new ObjectOutputStream(connection.getOutputStream());
oos.writeUtf("some message"); //or use oos.writeObject("some message");
oos.flush();
.....
【讨论】:
【参考方案7】:readline() 和 read() 将在套接字未关闭时被阻塞。所以你应该关闭套接字:
Socket.shutdownInput();//after reader
Socket.shutdownOutput();//after wirite
而不是 Socket.close();
【讨论】:
以上是关于BufferedReader readLine() 块的主要内容,如果未能解决你的问题,请参考以下文章
为啥 BufferedReader read() 比 readLine() 慢得多?
套接字,BufferedReader 在 readLine() 处挂起
在 while 循环中正确使用 BufferedReader.readLine()