Foreign
Foreign

Reputation: 405

How to properly read an InputStream with multiple contents

public static void main(String[] args) throws Exception
{
    // Server sends 3 numbers to the client
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bos.write(1000);
    bos.write(2000);
    bos.write(3000);

    // Client receive the bytes
    final byte[] bytes = bos.toByteArray();

    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
    System.out.println(bis.read());
    System.out.println(bis.read());
    System.out.println(bis.read());
}

The code above is breaking because bis.read() returns an int in the range 0 to 255

How can I receive those numbers properly? Should I use a delimiter and keep reading the stream until I find it? If so, what if I'm sending multiple files, I think if the delimiter as a single byte it could matched somewhere in the file and also break.

Upvotes: 3

Views: 1839

Answers (3)

Jochen Reinhardt
Jochen Reinhardt

Reputation: 843

Use decorators for your streams!

All you have to do is to wrap your Output- and InputStream by java.io.ObjectOutputStream / and java.io.ObjectInputStream. These classes support writing and reading ints (a 4-byte value) with a single method call to writeInt/readInt.

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(bos);
    os.writeInt(1000);
    os.writeInt(2000);
    os.writeInt(3000);
    os.close();

    // Client receive the bytes
    final byte[] bytes = bos.toByteArray();

    ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bytes));
    System.out.println(is.readInt());
    System.out.println(is.readInt());
    System.out.println(is.readInt());

Don't forget to close the streams. Use try/finally or try-with-resources.

Upvotes: 3

Onkar Vaidya
Onkar Vaidya

Reputation: 138

Can you try ByteBuffer class?

ByteStream is just a stream of bytes. It doesn't understand integer which actually needs more than one byte. If you print bytes.length it will return you 3. Surely you need more bytes than that. Allocate 4 bytes before you write an integer and then write to it. Check out this class above. Hope that helps!

Upvotes: 0

Mark Bramnik
Mark Bramnik

Reputation: 42541

Byte stream is a stream of bytes. So if you're reading stream and want to differentiate between different parts of the stream then you should "create" some sort of protocol.

Here are some ideas that can be relevant:

  1. Use delimiter as you've stated by yourself, If you're concerned about the length - do not one byte length, but something more unique - something that you're sure you won't see in the parts themselves.

  2. At the beginning of the part allocate N bytes (2-4 or maybe more, depending on data) and write the size of the part that will follow. So that when you create the stream (writer), before actually streaming the "part" - calculate its size and encode it. This is a protocol between reader and writer. When you read - read the size (=N bytes for example), and then read N bytes. Now you know that the part is ended, and the next part (again, size + content) will follow

Upvotes: 0

Related Questions