0

A web service is providing a binary chunked application/octet-stream. I have to build a reading client in java. I know the structure from some documentation and would like to use that stream as an ObjectInputStream, but before I can call any self made readObject methods, this approach fails, due to java.io.StreamCorruptedException: invalid stream header.

What's the best way to populate java objects from such a byte stream?

BTW: Data is coming in as LittleEndian, texts as 16bit chars preceeded by 4 byte size info, e.g.

03 00 00 00 41 00 62 00 63 00 (hex)

would result in "Abc"

datafiddler
  • 1,755
  • 3
  • 17
  • 30
  • 1
    `ObjectInputStream` assumes the processed data is the result of the java marshaling process. The error you encounter happens because your data stream does not start with the usual `aced 0005` bytes – Aaron Aug 30 '16 at 13:33
  • 1
    You will have to do something like swap the bytes, use `DataInputStream` and populate the object. – bradimus Aug 30 '16 at 13:36
  • @bradimus: As I first have to swap bytes before a dataInput.readInt() would work, what's the benefit of DataInputStream over the basic InputStream? Here (http://stackoverflow.com/questions/14827398/converting-byte-array-values-in-little-endian-order-to-short-values) I learned that manually shifting bytes is preferable over using endianness-aware classes. – datafiddler Aug 30 '16 at 14:07
  • You’ll need to be more specific than “populate Java objects.” Are you just reading a length value and characters, or is there other data? What Java objects do you want to create/populate? – VGR Aug 30 '16 at 14:15
  • @VGR : my own objects are pretty specific and are composed of basic / primitive types. ( E.g. table schema metadata, and table data - primitive types, strings, timestamps and eventually arrays of those). My question was more about the general approach to a foreign stream. – datafiddler Aug 30 '16 at 15:18
  • I am not clear on the meaning of “foreign stream.” Reading an InputStream is the same regardless of its source. Are you asking how to best deal with little-endian data? – VGR Aug 30 '16 at 15:32
  • @VGR: With "foreign stream" I was trying to emphazise it's something not created by myself and not by java code. Thus not being something ideally to be interpreted as an object stream (which I realized meanwhile, thinking and discussing about). Meanwhile yes, little-endian data was the remaining question after "do not bother about overriding readObject()" . Thanks for providing feedback. – datafiddler Aug 30 '16 at 15:46

1 Answers1

0

Sometimes it's faster to do it from scratch ( or with the tools you already know ) than to search for more sophisticated solutions. I simply created my own dedicated DataInputStream:

import java.io.IOException;
import java.io.InputStream;

public class LittleEndianInputStream {
    private InputStream s;  

    public LittleEndianInputStream (InputStream in) { s = in; }

    boolean readBoolean() throws IOException {return (s.read() == 1);}

    int readInt() throws IOException {return s.read() | s.read() << 8 | s.read() << 16 | s.read() << 24; }

    char readChar() throws IOException {return (char)(s.read() | s.read() << 8); }

    String readString() throws IOException {
        int len = readInt();
        char [] tarray = new char[len];
        for (int i = 0; i < len; i++ ) tarray[i] = readChar();
        return new String(tarray);
    }
}

To be expanded for more data types as needed...

Alternate Solutions are still welcome ;)

datafiddler
  • 1,755
  • 3
  • 17
  • 30