java中如何判断InputStream的结尾

发布于 2024-10-30 15:33:21 字数 1008 浏览 4 评论 0原文

我正在尝试使用 Socket 程序从服务器读取字节,即我正在使用 InputStream 读取字节。如果我传递长度大小,我就可以读取字节,但我不确定长度是多少。所以我无法初始化字节数组。

我还尝试了 while (in.read() != -1) ,我观察到发送数据时循环工作正常,但循环后的下一行不可执行,我觉得它仍然在流中查找数据,但没有数据。如果我关闭服务器连接,那么我的客户端将执行循环后面的下一行。

我不确定我哪里出错了?

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

但没有输出:- 循环结束

请指导我该如何关闭循环?

期待您的回复。提前感谢大家。

I am trying to read bytes from server using Socket program, ie I am using InputStream to read the bytes. If I pass the length size I am able to read the bytes, but I am not sure what may be the length. So I am not able initialize the byte array.

Also I tried while (in.read() != -1), I observered it loop works fine when the data is sent, but the next line after the loop is not executable, I feel its still looking for the data in the stream but there is no data. If I close the Server connection, then my client will execute the next line followed to the loop.

I am not sure where I am going wrong?

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");

I get the output as:-

,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

But no output for :-
End Of loop

Please guide how shall I close the loop?

Looking forward for you response. Thanking you all in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

触ぅ动初心 2024-11-06 15:33:21

它正在寻找更多数据,因为没有任何信息告诉它不会有更多数据。网络的另一端可以随时发送更多数据。

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

  • 在消息结束时关闭连接
  • 输入消息的长度在数据本身之前
  • 使用分隔符;一些在普通数据中永远不会出现的值(或者总是会以某种方式转义)

就我个人而言,我倾向于尽可能使用长度前缀;它使读取代码变得更加简单,但仍然允许同一连接上有多个消息。

(此外,我同意丹尼尔的观点,您应该使用 read 的重载,它一次读取整个缓冲区,而不是单个字节。这会更有效 - 但从根本上来说并不是改变当前问题的性质。)

It's looking for more data because nothing's told it that there won't be more data. The other end of the network could send more data at any time.

It's not clear whether you're designing the client/server protocol or just trying to implement it, but typically there are three common ways of detecting the end of a message:

  • Closing the connection at the end of the message
  • Putting the length of the message before the data itself
  • Using a separator; some value which will never occur in the normal data (or would always be escaped somehow)

Personally I favour length-prefixing when possible; it makes the reading code significantly simpler, but still allows multiple messages on the same connection.

(Additionally, I agree with Daniel that you should be using the overload of read which reads a whole buffer at a time, instead of a single byte. This will be much more efficient - but doesn't fundamentally change the nature of your current issue.)

迷乱花海 2024-11-06 15:33:21

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

您不退出循环的原因是输入流的结束仅在服务器端关闭其套接字后发生在客户端。 (或者更准确地说,在关闭其套接字输出流之后...或等效的...并且关闭事件已传播到客户端。)

在该事件发生之前,服务器可能会决定写入更多数据到插座。因此,客户端读取会阻塞......直到它获取更多数据或看到表明服务器端已关闭的协议事件。

(实际上,其他事件可以解锁客户端读取,但它们都会导致某种类型的 IOException,并且可能会导致您无法从中读取更多数据的流。)


现在,如果您现在不想关闭服务器端,因为您想稍后在套接字上发送更多内容,您将不得不更改应用程序协议以使用某种成帧机制。例如,服务器可能发送一个帧(或记录,或其他任何内容),其中包含字节计数,后跟给定的字节数。或者,它可以使用不同的字节值或字节序列来标记帧的结束。

I think you've actually answered your own question.

The reason you are not exiting the loop is that the end of input stream only happens on the client end after the server end closes its socket. (Or more precisely, after it closes its socket output stream ... or the equivalent ... and the close event has propagated to the client end.)

Until that event happens, it is possible that the server could decide to write more data to the socket. So the client-side read blocks ... until it either gets more data or it sees the protocol event that says that the server end has closed.

(Actually, other events can unblock the client read, but they will all result in an IOException of some kind, and probably a stream that you can't read any more data from.)


Now, if you don't want to close the server end now because you want to send more stuff on the socket later on, you are going to have to change your application protocol to use some kind of framing mechanism. For instance, the server might send a frame (or record, or whatever) consisting of byte count followed by the given number of bytes. Alternatvely, it could use a distinguished byte value or byte sequence to mark the end of a frame.

倾其所爱 2024-11-06 15:33:21

你可以运行这个例子。

如果您要等待流结束,则必须在发送端关闭它才能接收 EOF (-1)。

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

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.

You can run this example.

If you are going to wait for the end of the stream you have to close it on the sending side for and EOF (-1) to be received.

For sending multiple binary messages I prefer to send the length before the message as it allow the code to read large blocks at once (i.e. because it knows how much it is going to get)

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();

prints

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.
梦毁影碎の 2024-11-06 15:33:21

对于一次性 TCP 连接,这对我有用:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
InputStream input = socket.getInputStream();
final byteSize = 1024;
byte[] data = new byte[byteSize];
int nRead;
while ((nRead = input.read(data, 0, data.length)) != -1) {
    buffer.write(data, 0, nRead);
    if (nRead < byteSize) {
        break;
    }
}
buffer.flush();
byte[] byteArray = buffer.toByteArray();

作为参考,这改编自 Java 输入流到字节数组和字节缓冲区

For a one time TCP connection, this works for me:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
InputStream input = socket.getInputStream();
final byteSize = 1024;
byte[] data = new byte[byteSize];
int nRead;
while ((nRead = input.read(data, 0, data.length)) != -1) {
    buffer.write(data, 0, nRead);
    if (nRead < byteSize) {
        break;
    }
}
buffer.flush();
byte[] byteArray = buffer.toByteArray();

For reference, this is adapted from Java InputStream to Byte Array and ByteBuffer.

近箐 2024-11-06 15:33:21

我遇到过类似的问题,in.read() 只是挂在数据末尾而不是返回 -1。

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

如果做不到这一点,请考虑使用 socket.setSoTimeout(reasonableValue) 这样至少您的应用程序不会永远挂起......

I've had a similar problem where in.read() just hangs at the end of the data rather than returning a -1.

If you have no control over the server code, is there a reliable marker you can detect in the returned data (e.g., </html>) and use that to end the reading loop?

Failing that, consider using socket.setSoTimeout(reasonableValue) so at least your app won't be kept hanging forever...

暮年慕年 2024-11-06 15:33:21

如果是 -1,则不会结束循环。将 65535 放入条件中,我 99% 确定它会停止循环。

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

In case -1 it does not end the loop. Put 65535 in the condition and i am 99% sure it will stop the loop.

while(dataInt != 65535){
    System.out.print(","+i+"--"+dataInt);
    i++;
    dataInt = this.in.read();
}
蹲墙角沉默 2024-11-06 15:33:21

我也遇到了问题,就是没有跳出循环。我的解决方案看起来与此类似:

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

I had also the problem that I did not come out of the loop. My solution looked similar to this:

while (in.ready()){
    System.out.print(","+i+"--"+dataInt);
    i++;
    dataInt = this.in.read();
}
情痴 2024-11-06 15:33:21

您可以在 while 循环之后安全地关闭流。 dataInt 为 -1 意味着没有更多内容可供读取。

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

如果 while 循环没有退出,则意味着流的另一端仍有数据正在写入。关闭另一端的流。
如果您可以在将数据写入流的位置发布代码,那将会很有帮助。

You can safely close the stream after the while loop. dataInt being -1 means that there is nothing more to read from it.

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

If the while loop is not exiting it means that there is still data being written at the other end of the stream. Close the stream at the other end.
If you can post code where you write data to stream that will be helpful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文