开发者

How to identify end of InputStream in java

开发者 https://www.devze.com 2023-02-22 15:06 出处:网络
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

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.


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.)


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.


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.


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.


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...


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


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消