Search code examples
javac++qtdeserializationqbytearray

Deserialize QByteArray to Java data types


I am currently working on a Client-Server connection.

The client is written in Java not using QT running on an Android phone, the server is written in C++ using the Qt framework.

The client recieves QByteArrays , QStrings and QLists, but I have no clue how to deserialize and interpret the incomming data.

The C++ source code that creates the packet that I have to read on the java client side looks like this:

QByteArray body;
QString string1, string2, string3;
QList<float> list;
qint8 recognitionCount;

QDataStream bodyStream(&body, QIODevice::WriteOnly);

bodyStream << recognitionCount;

bodyStream << string1.toUtf8()
<< string2.toUtf8()
<< string3.toUtf8()
<< list;

The connection between client and server is up and running fine. I understand how to read integers that the server sends me for example. I also know how to read bytes, but what am I supposed to do with these bytes? How can I format them to a String for example?

Can anyone help me out?

I really appreciate any help!


Solution

  • You can convert from Qt Strings to Java like this (according to this definition):

    final static int MAX_STRING_LENGTH = 10240; // arbitrary number
    private final static ByteBuffer stringBytes = ByteBuffer.allocate(MAX_STRING_LENGTH);
    
    static String readStringFromQTStream(final ObjectInputStream in) throws IOException {
      if (in.available() < (Integer.SIZE / 8)) { // check that there are at least 4 bytes for the length
        throw new IOException("Illegal data received: expected integer but only got " + in.available() + " bytes");
      }
      final int stringLength = in.readInt();
      if (stringLength == 0xFFFFFFFF) { // Qt for null string
        return null;
      }
      if ((stringLength < 0) || (stringLength > stringBytes.capacity())) { // check for malformed data
        throw new IOException("Illegal data received: string with supposed length of " + stringLength + " bytes");
      }
    
      stringBytes.clear(); // global var, not thread-safe!
      in.readFully(stringBytes.array(), 0, stringLength);
      stringBytes.flip();
      return StandardCharsets.UTF_8.decode(stringBytes).toString();
    }
    

    Please note that the ByteBuffer is reused, which is a good performance increase if you read data frequently, but this is of course not thread-safe without further code.