Как поменять 64-битное целое число при извлечении байтов из bytearray в С++?

Я пытаюсь прочитать пару байтов из byteData, как указано ниже в моем коде на С++. Фактическое значение в byteData представляет собой двоичный байтовый массив байтов в формате байтового байта BIG-ENDIAN. Поэтому я просто не могу просто "отличить" массив байтов от строки.

byteData массив байтов состоит из этих трех вещей -

First is `schemaId` which is of two bytes (short datatype in Java)
Second is `lastModifiedDate` which is of eight bytes (long datatype in Java)
Third is the length of actual `byteArray` within `byteData` which we need from `byteData`.
Fourth is the actual value of that `byteArray` in `byteData`.

Теперь я пытаюсь извлечь вышеуказанную конкретную информацию из byteData в С++... Как-то я могу извлечь schemaId, и значение, которое я получаю, также правильно. Теперь я не уверен, как извлечь из него другие вещи...

uint16_t schemaId;
uint64_t lastModifiedDate;
uint16_t attributeLength; // or it should be uint32_t?
const char* actual_binary_value;

while (result.next()) {
    for (size_t i = 0; i < result.column_count(); ++i) {
        cql::cql_byte_t* byteData = NULL;
        cql::cql_int_t size = 0;
        result.get_data(i, &byteData, size);

        // I cannot just "cast" the byte array into a String
        // value = reinterpret_cast<char*>(byteData);

        // this works fine
        schemaId = ntohs(*reinterpret_cast<uint16_t*>(byteData));

        // now how to retrieve lastModifiedDate, length of binary value and actual_binary_value from byteData?
        // the below doesn't works..
           lastModifiedDate = be64toh(*reinterpret_cast<uint64_t*>(data));

        // And how to extract other things as well?

    }

    // this prints out `9223090561897746107`  but it should print out `1289811105109`
    cout<< lastModifiedDate <<endl;

    // And print out other things..
}

Если кто-то должен увидеть мой java-код, тогда это мой код java -

    byte[] avroBinaryValue = text.getBytes();

    long lastModifiedDate = 1289811105109L;
    short schemaId = 32767;

    int size = 2 + 8 + 4 + avroBinaryValue.length; // short is 2 bytes, long 8 and int 4

    ByteBuffer bbuf = ByteBuffer.allocate(size); 
    bbuf.order(ByteOrder.BIG_ENDIAN);

    bbuf.putShort(schemaId);
    bbuf.putLong(lastModifiedDate);
    bbuf.putInt(avroBinaryValue.length);
    bbuf.put(avroBinaryValue);

    // merge everything into one bytearray.
    byte[] bytesToStore = bbuf.array();

    Hex.encodeHexString(bytesToStore)

Может ли кто-нибудь помочь мне в том, что я неправильно делаю в своем коде на С++ и почему я не могу извлечь из него lastModifiedDate из него и других полей? Насколько я понимаю, lastModifiedDate - это 64-битное целое число, так есть ли способ поменять здесь 64-битное целое число? Или какой-нибудь другой способ сделать преобразование?

Короче говоря, я пытаюсь извлечь schemaId, lastModifiedDate, avroBinaryValue.length и avroBinaryValue из этого байтового массива в С++..

Я могу извлечь schemaId, но теперь я застрял на других вещах...

Ответ 1

Ваш метод выглядит отлично, есть только две возможные проблемы, которые я вижу.

  • Ваш код, как показано, просто набрасывает переменную undefined data как uint64_t. Убедитесь, что вы фактически продвигаетесь через буфер данных и преобразуете правильные данные.

  • зависимость от платформы. Из того, что я видел, функции обмена 64-битными байтами (be64toh, betoh64, ntohll и т.д.) Не поддерживаются повсеместно на всех платформах. Возможно, вам придется использовать другую функцию на своей платформе и/или автоматически определять, что работает, если вы хотите, чтобы код был независимым от платформы. См. Аналогичные вопросы здесь и here, например.

Что касается того, как получить данные, что-то вроде этого должно работать:

int index=0;
schemaId = ntohs(*reinterpret_cast<uint16_t*>(&byteData[index]));
index += 2;
lastModifiedDate = be64toh(*reinterpret_cast<uint64_t*>(&byteData[index]));
index += 8;
attributeLength = ntohl(*reinterpret_cast<uint32_t*>(&byteData[index]));
index += 4;
actual_binary_data = (const char *)&byteData[index];