如何识别java中InputStream的结尾

我想从服务器读取字节使用Socket程序,即我使用InputStream来读取字节。 如果我通过长度大小,我可以读取字节,但我不知道可能是什么长度。 所以我不能初始化字节数组。

我也试过while (in.read() != -1) ,我观察到它循环工作正常,当数据发送,但循环后的下一行是不可执行的,我觉得它仍然在寻找stream中的数据但没有数据。 如果我closures服务器连接,那么我的客户端将执行循环的下一行。

我不确定我哪里错了?

 this.in = socket.getInputStream(); int dataInt = this.in.read(); while(dataInt != -1){ System.out.print(","+i+"--"+dataInt); i++; dataInt = this.in.read(); } System.out.print("End Of loop"); 

我得到的输出为: –

 ,1--0,2--62,3--96,4--131,5--142,6--1,7--133,8--2,9--16,10--48,11--56,12--1,13--0,14--14,15--128,16--0,17--0,18--0,19--48,20--0,21--0,22--0,23--0,24--0,25--1,26--0,27--0,28--38,29--114,30--23,31--20,32--70,33--3,34--20,35--1,36--133,37--48,38--51,39--49,40--52,41--49,42--55,43--49,44--52,45--52,46--54,47--55,48--50,49--51,50--52,51--48,52--53,53--56,54--51,55--48,56--48,57--57,58--57,59--57,60--57,61--57,62--57,63--57,64--56 

但是没有输出: – End Of loop

请指导我如何closures循环?

期待您的回应。 提前感谢你们。

它正在寻找更多的数据,因为没有人告诉它将不会有更多的数据。 networking的另一端可以随时发送更多的数据。

目前尚不清楚您是在devise客户端/服务器协议还是只是试图实现它,但通常有三种常见的方式来检测消息的结束:

  • 在消息结尾处closures连接
  • 在数据本身之前放置消息的长度
  • 使用分隔符; 一些在正常数据中永远不会发生的值(或者总是以某种方式逃脱)

就我个人而言,如果可能的话,我喜欢长度前缀。 它使阅读代码显着简化,但仍允许在同一连接上的多个消息。

(另外,我同意丹尼尔的看法,你应该使用read的重载,它一次读取整个缓冲区,而不是单个字节。这样做效率会更高 – 但并不会从根本上改变当前问题的性质。)

我想你已经回答了你自己的问题。

不退出循环的原因是inputstream的结束只在服务器端closures其套接字后发生在客户端。 (或者更确切地说,在它closures了它的套接字输出stream之后…或者等效的…并且closures事件已经传播到客户端。)

在事件发生之前,服务器可能决定将更多数据写入套接字。 所以客户端读取块…直到它获得更多的数据,或者它看到协议事件,说服务器端已经closures。

(实际上,其他事件可以阻止客户端读取,但是它们都将导致某种IOException ,并且可能是一个不能读取更多数据的stream。)


现在,如果您现在不想closures服务器端,因为您稍后要在套接字上发送更多的东西,您将不得不更改应用程序协议以使用某种成帧机制。 例如,服务器可能会发送一个帧(或logging,或其他),由字节数组成,然后是给定的字节数。 相反,它可以使用一个独特的字节值或字节序列来标记一个帧的结束。

你可以运行这个例子。

如果您要等待stream的结束,则必须在发送端closures它,并接收EOF(-1)。

对于发送多个二进制消息,我更喜欢在消息之前发送长度,因为它允许代码一次读取大块(即知道它将得到多less)

 ServerSocket ss = new ServerSocket(0); Socket s = new Socket("localhost", ss.getLocalPort()); Socket s2 = ss.accept(); final OutputStream out = s.getOutputStream(); out.write("Hello World!".getBytes()); out.close(); final InputStream in = s2.getInputStream(); for (int b = 0; ((b = in.read()) >= 0);) { System.out.println(b + " " + (char) b); } System.out.println("End of stream."); s.close(); s2.close(); ss.close(); 

版画

 72 H 101 e 108 l 108 l 111 o 32 87 W 111 o 114 r 108 l 100 d 33 ! End of stream. 

我有一个类似的问题,其中in.read()只是挂在数据的末尾,而不是返回-1。

如果您无法控制服务器代码,那么在返回的数据中是否有可靠的标记(例如“”),并使用它来结束读取循环?

如果不这样做,考虑使用socket.setSoTimeout(rationalValue),所以至less你的应用程序不会永远悬挂…

在-1的情况下,它不会结束循环。 把65535的条件,我99%肯定会停止循环。

 while(dataInt != 65535){ System.out.print(","+i+"--"+dataInt); i++; dataInt = this.in.read(); } 

while循环之后,您可以安全地closuresstream。 dataInt是-1意味着没有更多的东西要读取它。

http://download.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html#read ()

如果while循环没有退出,意味着数据stream的另一端仍然有数据被写入。 closures在另一端的stream。 如果你可以在你写数据的地方发布代码,那么这将对你有帮助。

我也有这个问题,我没有走出循环。 我的解决scheme看起来与此类似:

 while (in.ready()){ System.out.print(","+i+"--"+dataInt); i++; dataInt = this.in.read(); }