【问题标题】:Problems with InputStreamInputStream 的问题
【发布时间】:2012-07-06 06:42:05
【问题描述】:

以下是我将用于我的项目的代码 sn-p 的一部分。

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 进行 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;
    }
}

【问题讨论】:

  • 我们能看看你是如何初始化输入流的吗?
  • @LouisWasserman 我已经更新了我的代码。
  • 也不要使用StringBuffer。 StringBuilder 在 99% 的情况下是首选(正如它在 Javadoc 中所述)
  • @PeterLawrey 是的,我会改变它,谢谢。

标签: java inputstream outputstream


【解决方案1】:

我对 Android 上的 Apache Commons 也有同样的问题...... 输入流上的 read() 命令由于某种原因永远挂起。不,这不仅仅是阻止“直到数据可用”...... 我的调试信息显示有几个 100 chars available() ...但它只是在某些读取时随机阻塞。但是,每当我向 telnet 服务器发送内容时,该块就会突然释放,它会继续读取几个字符,直到它在某个任意点突然停止/再次阻塞!

我相信 Apache Commons 库中存在一些错误!这真的很烦人,因为没有什么可以做的......读取命令或其他任何东西都没有超时......

编辑:我能够绕过它...通过设置 TelNetClient.setReaderThread(false) ...显然,只要线程处理输入数据,库中就存在一个错误...当禁用它对我来说很好用!

【讨论】:

  • 这是个好消息。那么您现在如何从流中读取这些字节,基本上我想知道您在读取循环中设置的条件是什么。
【解决方案2】:

JavaDocs

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

简单来说:如果您的流结束(例如文件结束),read() 立即返回 -1。但是,如果流仍然打开但 JVM 正在等待数据(慢速磁盘、套接字连接),read()阻塞(不是真正挂起)。

您从哪里获取流?查看available() - 但请不要在循环中调用它会耗尽 CPU。

最后:将int/byte 转换为char 仅适用于ASCII 字符,请考虑在InputStream 之上使用Reader

【讨论】:

  • 是否有可能像没有可用字节但流仍然打开。我有点困惑,我只是问问。
  • 那么如何确保 InputStream 中当前存在多少字节(如果没有关闭)?我看到 available() 方法不能保证打开的 Stream 中可用的字节数。
  • @SubhajitRoy:你想达到什么目标?查看您想要阅读整个流(直到最后)并将其转换为String 的代码。你考虑过:IOUtils.toString(java.io.InputStream)吗?
  • 我必须实现这样的目标:我的 InputStream 和 OutputStream 将保持打开状态,直到 TelnetSession 的生命周期。现在,每当我必须为 Telnet 发送任何命令时,我都必须使用 OutputStream 并刷新它。命令发送后,结果(Response)来到InputStream。这个响应只不过是 InputStream 中一组新的可用字节。因此,您会看到我的 InputStream 不会关闭,但我必须获取那些新的可用字节并最终转换为我将用于在 .jsp 页面中显示的字符串。这就是我所需要的。 :)
【解决方案3】:

阅读文档

如果 InputStream 没有关闭,read() 将一直​​等待,直到 InputStream 上有更多数据。

我怀疑你是用套接字做的?这是最常见的地方。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    • 2014-07-07
    • 2015-03-26
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    相关资源
    最近更新 更多