2012-07-05 53 views
2

以下是我将用于我的项目的代码片段的一部分。InputStream的问题

public String fetchFromStream() 
{ 
    try 
    { 
     int charVal; 
     StringBuffer sb = new StringBuffer(); 

     while((charVal = inputStream.read()) > 0) { 
      sb.append((char)charVal); 
     } 
     return sb.toString(); 
    } catch (Exception e) 
    { 
     m_log.error("readUntil(..) : " + e.getMessage()); 
     return null; 
    } finally { 
     System.out.println("<<<<<<<<<<<<<<<<<<<<<<Called>>>>>>>>>>>>>>>>>>>>>>>>>>>"); 
    } 
} 

最初while循环开始工作很好。但是在从流中读取可能的最后一个字符后,我期望得到-1返回值。但这是我的问题开始的地方。代码被挂起,即使finally块也不会被执行。

我在Eclipse中调试此代码以查看运行期间实际发生的情况。我在while循环中设置了一个指针(调试),并不断监视StringBuffer逐个填充char值。但是,当检查while循环内部的条件时,突然发现调试控制器正在丢失,这是代码进入挂起状态的地方!也没有例外抛出!

这里发生了什么?

编辑::

这就是我得到我的InputStream。基本上我使用的是Apache Commons Net for Telnet。

private TelnetClient getTelnetSession(String hostname, int port) 
{ 
    TelnetClient tc = new TelnetClient(); 
    try 
    { 
     tc.connect(hostname, port != 0 ? port : 23); 

        //These are instance variables 
     inputStream = tc.getInputStream(); 
     outputStream = new PrintStream(tc.getOutputStream()); 

     //More codes... 

     return tc; 
    } catch (SocketException se) 
    { 
     m_log.error("getTelnetSession(..) : " + se.getMessage()); 
     return null; 
    } catch (IOException ioe) 
    { 
     m_log.error("getTelnetSession(..) : " + ioe.getMessage()); 
     return null; 
    } catch (Exception e) 
    { 
     m_log.error("getTelnetSession(..) : " + e.getMessage()); 
     return null; 
    } 
} 
+0

我们能否看到如何初始化输入流? – 2012-07-05 19:46:47

+0

@LouisWasserman我已更新我的代码。 – 2012-07-05 19:57:07

+3

也不要使用StringBuffer。在99%的案例中,StringBuilder是首选(因为它在Javadoc中声明) – 2012-07-05 19:59:09

回答

5

看那JavaDocs

从输入读取数据的下一个字节流。值字节在0到255范围内返回int形式。如果由于已达到流的末尾而没有可用字节,则返回值-1返回此方法阻塞,直到输入数据可用,流的末尾被检测到,或抛出异常。

简而言之:如果你的流结束了(例如文件结束),read()立即返回-1。但是,如果流仍然打开,但JVM正在等待数据(慢速磁盘,套接字连接),read()(不是真的挂起)。

你从哪里得到流?查看available() - 但请不要在耗费CPU的循环中调用它。

最后:铸造int/bytechar将只ASCII字符的工作,考虑的InputStream顶部使用Reader

+0

是否有可能没有可用的字节,但流仍处于打开状态。我有点困惑,我只是问。 – 2012-07-05 20:10:25

+0

那么如何确保InputStream中当前有多少个字节(如果尚未关闭)呢?我看到可用()方法不保证打开的流中可用的字节数。 – 2012-07-05 20:25:37

+0

@SubhajitRoy:你想达到什么目的?看看你的代码,你想读整个流(直到最后)并将其转换为'String'。你有没有考虑过:[''IOUtils.toString(java.io.InputStream)'](http://commons.apache.org/io/apidocs/org/apache/commons/io/IOUtils.html#toString(java.io .InputStream))? – 2012-07-05 20:31:29

2

阅读文档

阅读()会等到有对的InputStream更多的数据,如果InputStream的未关闭。

我怀疑你是用插座来做这个吗?这是这个问题最常见的地方。 “

”从输入流中读取下一个字节的数据。值字节在0到255范围内返回为int。如果由于已到达流末尾而没有可用字节,则值-1 。将返回此方法块,直到在输入数据可用,检测到流的末尾或者抛出异常”

0

我与Android上的Apache Commons有相同的问题... 输入流上的read()命令由于某种原因永远挂起。不,它不只是阻塞“直到数据可用”...我的调试信息显示,有几个100个字符可用()...但它只是在一些阅读时随机阻止。但是,无论何时我向telnet服务器发送一些内容,块都会突然释放,并且会继续读取几个字符,直到突然停止/在某个任意点阻止!

我相信Apache Commons库中有一些bug!这真的很烦人,因为没有太多的事情可以做......没有超时的读取命令或其他任何东西......

编辑:我能够解决它...通过设置TelNetClient .setReaderThread(false)...显然,只要一个线程处理输入数据,库中就存在一个错误......当它被破坏时,它对我来说工作得很好!

+0

这是一个好消息。所以你现在怎么从流中读取这些字节,基本上我想知道你在读循环中设置了什么条件。 – 2012-07-19 12:20:14