javaarraysbyteinputstreambytearrayoutputstream

Why ByteArrayOutputStream and ByteArrayInputStream not the same content?


I have a big problem during one of my unit tests in Java. I compare a byte array with an InputStream and I do not get the same result.

The example is below.

public final class ByteGetInputStreamExampleProblem
{
    public static void main( final String[] args ) throws Exception
    {
        final SecureRandom s = new SecureRandom() ;

        final ByteArrayOutputStream bos = new ByteArrayOutputStream() ;

        long bPut = 0 ;

        final byte[] buffer = new byte[ 2 ] ;

        while( bPut < 10 )
        {
            s.nextBytes( buffer ) ;
            bos.write( buffer ) ;
            bPut += buffer.length ;
        }

        final InputStream is = new ByteArrayInputStream( bos.toByteArray() ) ;

        System.out.print("A = ");

        for( int i = 0 ; i < bos.size() ; i++ )
            System.out.print( bos.toByteArray()[i] + ";" ) ;

        System.out.print("\nB = ");

        int c ;
        while( ( c = is.read() ) != -1 )
            System.out.print(c + ":");
    } ;
} ;

Output:

A = -3;-47;-121;37;-73;83;109;-54;20;106;

B = 253:209:135:37:183:83:109:202:20:106:


Solution

  • When you print the contents of A you print them as bytes. So it will print values between Byte.MIN_VALUE up to Byte.MAX_VALUE (-128 to 127).

    When you use is.read() you read the contents as a unsigned number passed to you as a int. This value will be between 0 and 255.

    You could get the same outputs by casting c to a byte, e.g.

    while( ( c = is.read() ) != -1 ){
        byte b = (byte)c;
        System.out.print(b + ":");
    }
    

    In essence you will either need to convert both numbers to be between 0 and 255 or between -128 and 127.

    You can convert the 0 to 255 range to the -128 to 127 by casting it to a byte.

    You can convert the -128 to 127 by doing value & 0xFF. This changes it to be within the 0-255 range.

    The code for read() in the ByteArrayInputStream is as follows:

    public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }