2011-05-13 60 views
0

我想通过使用while循环从java中读取BufferedReader中的行。它会像应该那样遍历BufferedReader,但是当它从循环中断开时,它会'冻结'代码的执行。我试过调试代码,但执行提示在循环后丢失。不知道我做错了什么:当从BufferedReader中提取行时,无法在Java中循环while循环

代码片段:

BufferedReader reader = new BufferedReader(new InputStreamReader(yourSocket.getInputStream())); 
String nextLine = null; 

nextLine = reader.readLine(); 
while (nextLine != null){ //print all of input stream 
    System.out.println(nextLine); 
    nextLine = reader.readLine(); 
} 

我认为在没有线留在BufferedReader中的nextLine变量将返回null并打破循环。我试过手动打破循环,但它似乎并没有工作。同样,代码会打印BufferedReader的行,但是while循环后面的任何代码都不一定会运行。

如果这个信息不够,请让我知道。如有必要,我也可以通过完整的代码。

谢谢, 专利

+0

你从哪里得到读者? – bmargulies 2011-05-13 00:38:11

+0

什么协议通过套接字交换?套接字的服务器端是否关闭了它的流? – laz 2011-05-13 00:42:41

+0

你的套接字是一个套接字。我试图从另一个论坛复制代码,因为我试图处理HTTP请求。我将假定套接字不关闭流。问题在于,通过关闭流,我失去了BufferedReader的读取功能。 – Prusprus 2011-05-13 00:55:59

回答

1

问题出现是您的Reader是一个阻塞Socket,这将不指示结束流,直到对关闭连接缠绕(或侧关闭连接)。您可能已经阅读了所有可用的,但是当您尝试阅读更多内容时,底层的InputStream块会尝试从套接字读取更多数据。

当一些数据最终成为可用,InputStream将提供给Reader数据,并且一旦Reader已经看到足以构成一个完整的线—或结束流 —你会得到你最后一行退出Reader。尝试阅读下一行将最终返回null。

+0

这很有道理。上下文的升级:我试图通过套接字的输入流处理HTTP请求,然后读取HTTP请求的每一行。 我注意到,当我发送第二个HTTP请求时(通过刷新发送请求的Web浏览器),执行将继续执行我的代码,指示在刷新时流关闭。 现在的问题是,是否有更好的方法来处理inputStream,而不是将其放到BufferedReader中,还是有一种手动关闭流而不会对HTTP通信产生任何不良影响的方法? – Prusprus 2011-05-13 00:58:02

+0

在Java库中定义的委托流在调用close()时关闭它们的委托,这可能会让人烦恼。在你的情况下,如果关闭最外面的'BufferedReader',它将关闭'InputStreamReader',它将关闭由套接字提供的'InputStream',这会关闭套接字,根据'Socket#getInputStream()' 。你需要研究HTTP如何表达消息的* framing *。请参阅RFC 2616第4.4节,了解如何确定如何阅读完成消息(不再进一步)。 – seh 2011-05-13 18:23:23

2

从插座读取是一个阻塞调用。你的程序不知道另一端已经写完socket的事实。您通常必须使用一些标记或大小信息来识别另一端已完成写入套接字的程序。一旦你读了那个标记,你就从循环中退出了。这种行为与阅读说明文件有所不同 - 当您到达文件末尾时,readLine()方法被调用时可以返回null,您可以像在示例中那样退出。

0

自己编写了一些类似的代码来探索如何在Java中处理HTTP请求,我不相信BufferedReader的行为与从用于传输HTTP请求的Socket读取兼容,因为如前所述,如果没有更多数据要读取,readLine()会阻止,因此您的应用程序将挂起。根据HTTP规范,客户端在写入请求后保持打开状态,所以readLine()只是等待有更多数据可用。尝试检测HTTP请求最后一行的结尾\ n \ r对于从readLine()返回的行也不起作用,因为它会删除任何行尾字符组合:\ n,\ r或\ r \ ñ。

标题和请求正文之间也包含一个空白行,所以如果您要查找空白行作为消息的终止,则需要检查它不是标题和正文之间的行。

我认为通过readState(byte [])从InputStream中逐字符读取字符是一种解决方法 - 它将读取最大字节[]的大小,并在遇到流结束时终止读取。

0

我刚刚回答了其他人的帖子。 My cheater way around this.

使用循环像你...

String line; 
while ((line = in.readLine()) != null) { 
    System.out.println(line); 
    sleep(in); 
    if(!in.ready()){ 
     break; 
    } 
} 

有一个骗子办法,我想通了。

private static void sleep(BufferedReader in) throws IOException { 
    long time = System.currentTimeMillis(); 
    while(System.currentTimeMillis()-time < 1000){ 
     if(in.ready()){ 
      break; 
     } 
    }  
} 

这可能是草率的,但如果你作出这样的等待的时间量,只是继续检查,如果是的BufferedReader睡眠法“准备好了。”如果是的话,你可以爆发,但当你出来时再检查一次。 - 也许你可以只返回一个布尔值而不是检查两次,但概念就在那里。