InputStream 的 available() 倾向于停止
Posted
技术标签:
【中文标题】InputStream 的 available() 倾向于停止【英文标题】:InputStream's available() tends to halt 【发布时间】:2012-05-28 12:40:31 【问题描述】:这是一个有点晦涩难懂的问题,似乎只在我使用某些计算机时才会发生。 我今天在我们学校的 XP 计算机上遇到了这个问题,我似乎无法在我的家用计算机 (W7) 上复制这个问题。
无论如何,每当我使用这段代码(其中:int avail, InputStream socket, byte[] buffer, String output
)时,在 Java 中读取/写入套接字往往会出现问题:
while( (avail = input.available()) > 0 )
read = input.read( buffer );
output += new String( buffer, 0, read );
这似乎是有道理的(读取所有数据,直到没有数据可用于临时缓冲区,然后是字符串),但在我们学校的计算机上(使用 IE7 测试它),整个事情不知何故暂停了。我在想 input.available() 导致它以某种方式阻塞,因为线程只是继续运行而没有到达端点......实际上只是在某处暂停。
哦,我忘了说:每当我在调试模式下运行它并逐步执行每一行时,它都完全按照它应该的方式工作......这让我更加困惑。
当我回到家复制这个问题时,它工作得很好(只使用 Firefox 和 IE8)。我不知道有什么比这更好的选择。
PS: 如果缓冲区足够大,我只是使用:
read = input.read( buffer );
output += new String( buffer, 0, read );
它工作得很好,但总是担心发送的数据会超过缓冲区大小。
【问题讨论】:
read
将阻塞,直到检测到输入结束或某些数据可用。诚然 available() > 0
应该表明某些数据实际上可以在没有阻塞的情况下使用,重要的是要记住 available()
只是一个估计。
【参考方案1】:
您以错误的方式考虑available()
。那个方法tells you approximately how many bytes can be read right now,没有阻塞。对于您正在尝试做的事情,普遍接受的成语是
int length;
while ((length = in.read(buffer)) != -1)
output += new String(buffer, 0, length);
或类似的东西(未编译/测试)。
更新:我认为您误解了“流结束”的概念。 “流的结束”并不意味着您要读取的所有数据都已被读取。这意味着没有,也永远不会有其他可阅读的内容。例如,这可能意味着您正在读取一个文件并且已经结束,或者这可能意味着您正在从内存中的字节数组中读取并且已经结束。这些是“流的结束”。
在您的问题中,您表示或至少暗示您是reading from a Socket。您是否知道在关联的 Socket 或连接的远程端关闭之前,您永远不会到达该流的末尾?仅仅因为你从它那里收到了一点数据并不会让它成为流的结尾。
【讨论】:
我刚刚尝试过,它似乎在尝试阅读时卡住了。 预计会阻止read(),直到您到达流的末尾。你有证据证明你已经到达直播的末尾吗? 好吧,当我调试它时,它会读取整个 Steam(它在输出中有正确的数据),然后退回到 while 语句,我无法继续。【参考方案2】:为什么不使用缓冲阅读器?比如:
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String output = "";
try
String readLine = null;
while ((readLine = reader.readLine()) != null)
output += readLine + "\n";
catch (IOException e)
System.err.println("Error: " + e);
System.out.println("Read from Socket:" + output);
【讨论】:
也试过了。我知道这应该有效,但它有同样的问题。【参考方案3】:您的代码无效。这是对available()
的滥用。它所做的只是告诉你有多少字节可用于读取而不阻塞。它不能用于指示对等方将发送多少字节,并且与对等方消息没有必然关系。 TCP 中没有消息,只有一个字节流。如果要读取 EOS,只需删除 available()
测试并读取,直到它返回 -1。如果您想阅读一条消息,对等方将不得不以某种方式为您划定界限,例如通过带外终止符、长度词前缀或自描述协议(如对象序列化或 XML)。
它在调试模式下“工作”,因为您通过断点从根本上改变了时序。这进一步证明了您所做的事情是不正确的。
【讨论】:
以上是关于InputStream 的 available() 倾向于停止的主要内容,如果未能解决你的问题,请参考以下文章
Java InputStream函数`available()`如何用C语言实现?