aspose file tools*
The moose likes I/O and Streams and the fly likes Reading a stream of bytes from a socket. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » I/O and Streams
Bookmark "Reading a stream of bytes from a socket." Watch "Reading a stream of bytes from a socket." New topic
Author

Reading a stream of bytes from a socket.

Susan Smith
Ranch Hand

Joined: Oct 13, 2007
Posts: 224
I'm reading a stream of bytes from a socket

Supposedly,
The first 4 bytes would give me either "2001"/ "2002"/ "2003"/ "2004"
The second 4 bytes would give me information about the number of bytes contained in the data portion of the message.
The 9th bytes to N would give me the data portion of the message.

I've tried to do these lines of codes below to try to get the first 8 bytes


Below is the System.out.print result for the first 8 bytes:



I don't understand what does this mean? I'm not sure whether I do something wrong or not.
Does this mean that there's something wrong with the stream.
Could someone please advice?

Thank you
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
First, the available() method is almost completely useless, and should be ignored here. It doesn't tell you how many bytes will eventually be available; it tells you how many are avaailable right now. Often you just need to wait for the rest of the data to be available. In general, if you want to read something until the end, check the return value of the read() method. If it returns -1, the stream is done. until then, just keep reading. See Available Doesn't Do What You Think It Does for more info.

It seems odd to read the data first with a DataInputStream to fill a byte[] array, then read that byte array with a ByteArrayInputStream and another DataInputStream. Seems like you're making more work for yourself there. I would probalby just use the first DataInputStream to do everything.

I don't see anything in your code which is taking the first 4 bytes, ro the first 8 bytes, and doing something special with them. I see code that takes the first 64 bytes, but I don't understand why you would want to do that.

If the first four bytes represent a number, it's important to know how the number was written. Was it written as text? (Probably not, based on the unprintable characters you're seeing.) Or was it written using some binary format? The most likely option is that it was written in the same format that writeInt() and readInt() use - methods on DateInputStream and DataOutputStream. See the API for more info. If that's the case then you should simply call readInt() twice to read the two numbers.

On further study, I don't think that's the case. Have you studied how binary and hexadecimal numbers work? You may need some special tricks to convert these four bytes into a single number. There are a number of ways to do this, but I don't know how much you know about manipulating bits and bytes. You can think of the four bytes as a number in base 256, where each byte is one digit. If the bytes were in order with the most significant byte first, you could just use readInt(). Instead, it looks to me like they're in the reverse order instead. You could try reordering the bytes before you use readInt(). Or you could use some other bit manipulation (e.g. shift operators) to push the bytes around and form a new int out of them. There's also a relatively simple way to read the numbers using a java.nio.ByteBuffer, if you're familiar with those - but if you're not, it may be better to use methods you are more familiar with. Does any of this sound familiar?
[ November 09, 2007: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, Twister
Susan Smith
Ranch Hand

Joined: Oct 13, 2007
Posts: 224
Thanks for the reply.

I do this now:



And here is the result of the System.out.println() which doesn't look plausible at all.

Susan Smith
Ranch Hand

Joined: Oct 13, 2007
Posts: 224
>> On further study, I don't think that's the case.
How do you know it's not the case?

>> Instead, it looks to me like they're in the reverse order instead.
>> You could try reordering the bytes before you use readInt().
I'm not too familiar about reordering the bytes. How can we tell it's in reverse order?

>> There's also a relatively simple way to read the numbers using a
>> java.nio.ByteBuffer, if you're familiar with those - but if you're not,
>> it may be better to use methods you are more familiar with. Does any of >> this sound familiar?
No, it's not familiar to me. But I will do some reading about it.
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Susan Smith:
Thanks for the reply.

I do this now:



And here is the result of the System.out.println() which doesn't look plausible at all.



The readInt() method presumes big endian, and it looks like your data was written little endian. Try this:

int date = dataInputStream.readInt();
date = Integer.reverseBytes(date); // requires jdk 1.5
System.out.println("date:" + date);
int bufSize = dataInputStream.readInt();
bufSize = Integer.reverseBytes(bufSize);
System.out.println("bufSize:" + bufSize);

You should see 2001 and 44082 printed.

If you can't presume jdk 1.5 or better, it wouldn't be hard to write your own reverseBytes() method.


bitguru blog
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Jim]: On further study, I don't think that's the case.

[Susan]: How do you know it's not the case?

[Jim]: Instead, it looks to me like they're in the reverse order instead. You could try reordering the bytes before you use readInt().

[Susan]: I'm not too familiar about reordering the bytes. How can we tell it's in reverse order?


Brian and I both looked at the numbers printed out:

-47 7 0 0

As binary bytes, these are

1101 0111 0000 0000

Or in hex

D1 07 00 00

If we convert that to a long using big-endian, most significant byte is first, that's 3506896896. Which doesn't seem to mean anything. But if we use little-endian, least significant byte first, that's 2001, which is one of the expected values. So it looks like the least significant byte is first, which is opposite what writeInt() and readInt() assume.

I skipped a fuller explanation because it can be fairly long, and I don't know how much you already know about converting between different bases. Ultimately it's probably easier to read up on this from some other source if you can.

Or a simple way to do it in Java without necessarily understanding the details is:


And to reorder the bytes for little-endian without Java 5, you could just insert this after the first line:

using

[ November 12, 2007: Message edited by: Jim Yingst ]
Susan Smith
Ranch Hand

Joined: Oct 13, 2007
Posts: 224
Thank you guys. It's working now.

By the way, I have one simple JAVA question related to this project that I'm working on.
I'm not sure if I should post it in different post or not. But here's my question:


For the readFully() method in DataInputStream class, I know the method will block until a certain criteria occurs like below
This method blocks until one of the following conditions occurs:
b.length bytes of input data are available, in which case a normal return is made.
End of file is detected, in which case an EOFException is thrown.
An I/O error occurs, in which case an IOException other than EOFException is thrown


What I want to know is whether readInt() will do the same thing or not. Will it also block? It doesn't say anything about blocking in the API.
Susan Smith
Ranch Hand

Joined: Oct 13, 2007
Posts: 224
On a second thought, maybe I should post in different thread so I can give example:

http://www.coderanch.com/t/278776/Streams/java/Does-readInt-DataInputStream-class-block
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Reading a stream of bytes from a socket.