这是一个模糊不清的问题,只有当我在某些计算机上时才会发生。 我今天在我们学校的XP电脑上遇到这个问题,我似乎无法在家用电脑上复制这个问题(W7)。
无论如何,每当我使用这段代码时,读取/写入Java中的套接字都会出现问题(其中:int avail, InputStream socket, byte[] buffer, String output
):
while( (avail = input.available()) > 0 )
{
read = input.read( buffer );
output += new String( buffer, 0, read );
}
它似乎有意义(读取所有数据,直到没有数据可用于临时缓冲区,然后到字符串),但在我们学校的计算机上(使用IE7测试它),整个事情以某种方式暂停。我认为input.available()导致它以某种方式阻塞,因为线程只是在没有到达端点的情况下保持运行...实际上只是暂停某个地方。
OH,我忘了提及:每当我在调试模式下运行它并逐步执行每一行时,它的工作方式完全像它应该......这让我更加困惑。
当我回到家中复制这个问题时,它运行得很好(只使用Firefox和IE8)。我不知道什么是更好的替代方案。
PS: 如果缓冲区足够大,我只使用:
read = input.read( buffer );
output += new String( buffer, 0, read );
它工作得很好,但总是担心发送的数据会超过缓冲区大小。
答案 0 :(得分:3)
你正在考虑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或连接的远程端关闭之前,您永远不会到达该流的末尾?仅仅因为你从它那里收到了一些数据并没有使它成为流的末尾。
答案 1 :(得分:1)
为什么不使用缓冲读卡器?类似的东西:
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);
答案 2 :(得分:1)
您的代码无效。这是对available()
的误用。它所做的只是告诉你可以在没有阻塞的情况下读取多少字节。它不能用于指示对等体将发送多少字节,并且它与对等消息没有必要的关系。 TCP中没有消息,只有字节流。如果要读取EOS,只需删除available()
测试并读取直到它返回-1。如果你想阅读一条消息,对等体必须以某种方式为你划分它,例如通过带外终结符,长度字前缀或自描述协议(如对象序列化或XML)。
它在调试模式下“有效”,因为您通过断点彻底改变了时序。这进一步证明了你所做的不正确。