Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / August 2006

Tip: Looking for answers? Try searching our database.

Bytes coming through as -1

Thread view: 
AndrewTK - 02 Aug 2006 16:31 GMT
I am trying to read binary data from a network input stream but am
having a hard time at it. Consider the following:

    public static void main(String[] args) throws Exception {
        ServerSocket serversock = new ServerSocket(1234);

        while(true) {
            try {
                Socket s = serversock.accept();
                test(s.getInputStream(), s.getOutputStream() );
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void test(InputStream in, OutputStream out) throws
IOException {
        byte[] trash = new byte[10];
        int rcount;
        while( (rcount = in.read(trash)) != -1) {
            for(byte b : trash) {
                if(b ==-1) {System.out.print(".");}
            }
        }
    }

So far straightforward. It reads from the input stream and discards the
bytes. It also prints a full stop each time it encounters a byte
/inside the buffer/ that comes through as -1.

In theory, this should never happen: if a byte is -1, it comes out of
the read() method as such, which is normally a flag for read(byte[],
int, int) to stop reading.

However, the above code does print out a full set of dots when I run
the program - I have a form which connects to this server program and
sends a ZIP file to it. Try:

<html><body>
<form action="http://127.0.0.1:1234/"  method="POST"
enctype="multipart/form-data">
<input type="file" name="zfile" />
<input type="submit value="send" />
</form></html></body>

When I try to read the ZIP data, expecting -1 at the end of the stream,
reading gets -1 bang in the middle of the data. I am aware that EOS
would occur long after the file data ended, but that's not the point -
I can't even reach the end of the file data.

Any suggestions?

Andrew
Rogan Dawes - 02 Aug 2006 16:59 GMT
> I am trying to read binary data from a network input stream but am
> having a hard time at it. Consider the following:

>     public static void test(InputStream in, OutputStream out) throws
> IOException {
[quoted text clipped - 6 lines]
>         }
>     }

First problem:

     public static void test(InputStream in, OutputStream out) throws
 IOException {
         byte[] trash = new byte[10];
         int rcount;
         while( (rcount = in.read(trash)) != -1) {
             for(int i=0; i<rcount; i++) {
                 if(trash[i] ==-1) {
                                     System.out.print(".");
                                }
             }
         }
     }

You may not necessarily always read complete 10 byte chunks. Always
check how many bytes you actually got from the read, and then only use
that many bytes.

This may solve your problems.

Rogan
AndrewTK - 02 Aug 2006 17:07 GMT
> First problem:
>           while( (rcount = in.read(trash)) != -1) {
[quoted text clipped - 7 lines]
> check how many bytes you actually got from the read, and then only use
> that many bytes.

Thanks for pointing that out Rogan - silly me I should have spotted
that myself.

Unfortunately in my other files I do check for the number of bytes read
(hence the rcount - I was being lazy, I wrote the example specifically
for the post)

Corrected it gives:

    public static void test(InputStream in, OutputStream out) throws
IOException {
        System.out.println(in.getClass().getName() );
        byte[] trash = new byte[10];
        int rcount;
        while( (rcount = in.read(trash)) != -1) {
            for(int i=0;i<rcount;i++) {
                if(trash[i] == -1) {System.out.print(".");}
            }
        }
    }

The same output comes back. A load of dots.
dsjoblom@abo.fi - 02 Aug 2006 17:04 GMT
> I am trying to read binary data from a network input stream but am
> having a hard time at it. Consider the following:
[quoted text clipped - 30 lines]
> the read() method as such, which is normally a flag for read(byte[],
> int, int) to stop reading.

Note that the read methods return an int, not a byte. Java bytes are
signed, having a range of -128 to 127, so a value of -1 is a perfectly
good value for a byte read from a socket. For more info about
conversions between different types, see
http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1

Regards,
Daniel Sjöblom
AndrewTK - 02 Aug 2006 17:10 GMT
dsjob...@abo.fi wrote:

> Note that the read methods return an int, not a byte. Java bytes are
> signed, having a range of -128 to 127, so a value of -1 is a perfectly
> good value for a byte read from a socket. For more info about
> conversions between different types, see
> http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1

See Java API for InputStream:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStream.html#read()

"The value byte is returned as an int in the range 0 to 255. If no byte
is available because the end of the stream has been reached, the value
-1 is returned."
dsjoblom@abo.fi - 02 Aug 2006 17:15 GMT
> dsjob...@abo.fi wrote:
> >
[quoted text clipped - 10 lines]
> is available because the end of the stream has been reached, the value
> -1 is returned."

Which is what I said. It returns an int, not a byte.

Regards,
Daniel Sjöblom
AndrewTK - 02 Aug 2006 17:20 GMT
> > "The value byte is returned as an int in the range 0 to 255. If no byte
> > is available because the end of the stream has been reached, the value
> > -1 is returned."
>
> Which is what I said. It returns an int, not a byte.

It returns an int "in the range of 0 to 255" which does not include -1.

Although thinking of it further I suspect that once stored to the array
it might become signed once more...
dsjoblom@abo.fi - 02 Aug 2006 17:23 GMT
> > > "The value byte is returned as an int in the range 0 to 255. If no byte
> > > is available because the end of the stream has been reached, the value
[quoted text clipped - 6 lines]
> Although thinking of it further I suspect that once stored to the array
> it might become signed once more...

Yes. If the value is cast to a byte it will become signed if it is
between 128-255. Check out the language spec link I posted earlier.

Regards,
Daniel Sjöblom
dsjoblom@abo.fi - 02 Aug 2006 17:28 GMT
dsjob...@abo.fi wrote:
> > > > "The value byte is returned as an int in the range 0 to 255. If no byte
> > > > is available because the end of the stream has been reached, the value
[quoted text clipped - 9 lines]
> Yes. If the value is cast to a byte it will become signed if it is
> between 128-255. Check out the language spec link I posted earlier.

Although, I should add, the block read methods which read into an array
have no need to cast the return value, obviously.

Regards,
Daniel Sjöblom
AndrewTK - 02 Aug 2006 18:06 GMT
Thanks to all who posted.

I managed to discover and correct the bug. Thanks especially to Daniel
who triggered the thought needed.

My actual program used a custom input stream with an internal buffer.
Its read() method simply returned bytes that were in the buffer,
effectively as /signed/ ints rather than the unsigned int required....!
(I had presumed bytes remained unsigned and that returning ints was the
only way for read() to return -1 in an unsigned world...)

Up until now I had had no problem with the custom buffered stream, but
seen as sevral layers of buffereing were taking place in the new class
I was making/testing, signed ints were proliferating everywhere.

I had
   return buffer[offset++];
where I should have had
   return buffer[offset++] & 0xFF;
Appending that simple piece of code solved the problem entirely......!

So once again, thanks Daniel for putting me on the track of
signed/unsigned bytes!
Oliver Wong - 02 Aug 2006 17:16 GMT
> dsjob...@abo.fi wrote:
>>
[quoted text clipped - 10 lines]
> is available because the end of the stream has been reached, the value
> -1 is returned."

   But you're not calling the read() method! You're calling the
read(byte[]) method! They do different things.

   - Oliver
AndrewTK - 02 Aug 2006 17:25 GMT
>     But you're not calling the read() method! You're calling the
> read(byte[]) method! They do different things.
>
>     - Oliver

Thanks for pointing that out Oliver.

"The read(b, off, len) method for class InputStream simply calls the
method read() repeatedly."

and

" The read(b) method for class InputStream  has the same effect as:

read(b, 0, b.length) "

from the API.

So read() is called and used. If read() returns -1, read(byte[]) and
read(byte[], int, int) both should stop reading.

As previous posts indicate however, reading from the resulting byte
array may not necessarily yeild positive ints.

I pursue search elsewhere I guess.
Bill Medland - 02 Aug 2006 18:09 GMT
>>     But you're not calling the read() method! You're calling the
>> read(byte[]) method! They do different things.
[quoted text clipped - 21 lines]
>
> I pursue search elsewhere I guess.

Perhaps I can clarify; I think I see where you are misunderstanding what is
happening.

(Conceptually) The read() method tries to obtain a byte from the stream (a
value which in Java is between -128 and +127).  If it fails to read a byte
it returns the int value of -1.  If it succeeds in reading a byte (a value
between -128 and +127) it "converts" it to an int value in the range 0 to
255 and returns that.
The read(byte[]...) methods look at the value returned by read().  If it is
not -1 then it should be a value between 0 and 255.  That value is then
"reconverted" back to a byte; a value of -128 to +127 and that byte is
placed in the array.  (And so 255 becomes -1 in the array).  If the value
returned by read was -1 then that indicates that a byte was not obtained
and so the transfer stops (and that -1 is NOT put into the array).  The
read(byte[]...) method returns the number of characters read.
Thus any -1 in the array are values that were successfully read and had all
8 bits set.

If you want to interpret those bytes in the array as unsigned values in the
range 0-255 then you will need to convert them yourself (as read() does).
(However I would question why you would need to convert them like that;
read() does it so that it can return two facts in a single value, similarly
to what the C fgetc function does in returning either EOF or the integer
cast of a char.

Signature

Bill Medland

Nigel Wade - 03 Aug 2006 10:03 GMT
> I am trying to read binary data from a network input stream but am
> having a hard time at it. Consider the following:
[quoted text clipped - 50 lines]
>
> Andrew

I think you are confusing what is read from the stream and the return value of
read(). The read() method returns -1 when it encounters the end of the stream,
this has nothing whatever to do with the bytes which are read. The return value
of read() is either the number of bytes read or -1, not any of the bytes which
was actually read (all of which could be -1).

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Nigel Wade - 03 Aug 2006 10:05 GMT
>> I am trying to read binary data from a network input stream but am
>> having a hard time at it. Consider the following:
[quoted text clipped - 56 lines]
> of read() is either the number of bytes read or -1, not any of the bytes which
> was actually read (all of which could be -1).

Ooops, for read() substitute read(byte[]).

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

AndrewTK - 03 Aug 2006 14:19 GMT
> Ooops, for read() substitute read(byte[]).

As stated in an earlier post:

read(byte[]) and read(byte[], int, int) both use read() which returns
an unsigned integer.

Read() either returns the byte AS unsigned or -1, so read(byte[]) and
read(byte[], int, int) in my head pre-correction should have been
catching these -1 bytes etc etc etc

In a latter post I included (for the benefit of those posting further)
the source of the problem, and where the error lay: in home-grown
buffered readers (which in my case pre-correction were retrning the
legitimate negative bytes as negative, without "casting" them so to
say).


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.