Java - 扫描程序在没有输入时不会暂停

时间:2012-08-18 20:24:18

标签: java servlets network-programming java.util.scanner

我在本地Jetty下运行客户端和servlet。当我在客户端阅读邮件时,我会这样做:

in = new Scanner(conn.getInputStream());
StringBuffer messageBuffer = new StringBuffer();
while (in.hasNext()) {
   messageBuffer.append(in.next()).append(" ");
}

我希望当没有来自servlet的数据时,它应该冻结在

while (in.hasNext())

相反,我最终得到了空的messageBuffer,我必须处理它并一次又一次地调用该方法,直到我收到消息。为什么会这样?如何让它在while语句处停止并等待有数据进入?

以下是url连接的启动方式(一次,在客户端构造函数中):

try {
        url = new URL("http://localhost:8182/stream");
        conn = (HttpURLConnection) url.openConnection();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException ioE) {
        ioE.printStackTrace();
    }

4 个答案:

答案 0 :(得分:1)

来自Scanner doc的

  

next()和hasNext()方法及其原始类型的伴侣   方法(如nextInt()和hasNextInt())首先跳过任何输入   匹配分隔符模式,然后尝试返回下一个   令牌。 hasNext和next方法都可能阻止等待进一步   输入。 hasNext方法块是否与or无关   不会阻止其相关的下一个方法。

它说它可能会阻塞,但它不是api的一部分,它取决于你扫描的下划线实现。

无论如何,你需要通过以下方式实现等待:

while (!in.hasNext() && !stop){
   sleep();
}

答案 1 :(得分:1)

javadoc指出Scanner.hasNext()Scanner.next() 可能阻止。这实际上取决于潜在的InputStream。我个人不会使用Scanner来读取套接字,如果是那样的话。

更合理的方法可能是使用由InputStreamReader包裹的BufferedReader。另外值得一提的是,除非您需要线程安全,否则您应该使用StringBuilder而不是StringBuffer

BufferedReader br = 
    new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String input = null;
while ((input = br.readLine()) != null)
{
    sb.append(input).append(" ");
}

请注意,这是使用readLine(),可能会或可能不符合您的需求,具体取决于您收到的内容。它还假设连接的另一端在完成发送时将关闭。您可能希望使用其中一种read()方法并进行相应的解析。

编辑以添加以下评论:这实际上是阻塞读取在Java中的工作方式。这是一个完整的例子:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class App 
{
    public static void main( String[] args ) throws MalformedURLException, IOException
    {
        URL url = new URL("http://www.google.com");

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        BufferedReader br = 
            new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String input = null;
        while ((input = br.readLine()) != null)
        {
            sb.append(input).append(" ");
        }

        System.out.println(sb.toString());

    }
}

输出(此处为简洁起见,但它是整个页面):

<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage"><head> ...

答案 2 :(得分:0)

编辑:

尝试使用for循环而不是while循环,其中范围将从0到(长度-1)。你必须使用while(in.hasNextLine())找到长度并在其中放入长度计数器。完成填充messageBuffer(使用.close())后,忘记关闭扫描程序。试一试吧。它应该工作。

答案 3 :(得分:0)

根据我的经验,我一直试图避免阻塞,因此避免在hasNext()中使用Scanner方法。

相反,我使用了InputStream。您在代码中使用的InputStream:

conn.getInputStream();

然后,您可以使用InputStream方法 available()查看是否有任何信息通过。

因此,对于您的代码,我建议:

InputStream inStream = conn.getInputStream();
in = new Scanner(inStream);    
StringBuffer messageBuffer = new StringBuffer();    
while (in.available() <= 0)
{   
 try{
    Thread.sleep(100);
}
catch(InterruptedException e){}
}
messageBuffer.append(in.next()).append(" ");