QDataStream readQString() Как читать строку utf8

Я пытаюсь декодировать данные пакета UDP из приложения, которое кодирует данные с использованием методов Qt QDataStream, но у меня возникают проблемы при попытке декодировать строковые поля. Документы говорят, что данные были закодированы в utf8. Модуль python QDataStream имеет только метод readQString(). Кажется, что числа декодируются нормально, но указатель потока сбивается, когда первые строки декодируются неправильно.

Как я могу декодировать эти строки UTF8?

Я использую некоторую документацию из исходного проекта, интерпретирую кодировку: wsjtx-2.2.2.tgz NetworkMessage.hpp Описание в заголовочном файле

Header:
   32-bit unsigned integer magic number 0xadbccbda
   32-bit unsigned integer schema number

Например, есть сообщение о состоянии с такими комментариями:

Heartbeat     Out/In    0                       quint32
                             Id (unique key)        utf8
                             Maximum schema number  quint32
                             version                utf8
                             revision               utf8

пример данных из сокета при получении сообщения о состоянии:

б'\xad\xbc\xcb\xda\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x06WSJT-X\x00\x00\x00\x03\x00\x00\x00 \x052.1.0\x00\x00\x00\x0624fcd1'

def jt_decode_heart_beat(i):
    """
    Heartbeat     Out/In    0                      quint32
                             Id (unique key)        utf8
                             Maximum schema number  quint32
                             version                utf8
                             revision               utf8
    :param i: QDataStream
    :return: JT_HB_ID,JT_HB_SCHEMA,JT_HB_VERSION,JT_HB_REVISION
    """
    JT_HB_ID = i.readQString()
    JT_HB_SCHEMA = i.readInt32()
    JT_HB_VERSION = i.readQString()
    JT_HB_REVISION = i.readQString()
    print(f"HB:ID={JT_HB_ID} JT_HB_SCHEMA={JT_HB_SCHEMA} JT_HB_VERSION={JT_HB_VERSION} JT_HB_REVISION={JT_HB_REVISION}")
    return (JT_HB_ID, JT_HB_SCHEMA, JT_HB_VERSION, JT_HB_REVISION)

while 1:
    data, addr = s.recvfrom(1024)
    b = QByteArray(data)
    i = QDataStream(b)
    JT_QT_MAGIC_NUMBER  = i.readInt32()
    JT_QT_SCHEMA_NUMBER = i.readInt32()
    JT_TYPE = i.readInt32()

    if JT_TYPE == 0:
        # Heart Beat
        jt_decode_heart_beat(i)
    elif JT_TYPE == 1:
        jt_decode_status(i)

person baler1992    schedule 07.08.2020    source источник
comment
Еще немного просмотрел документы и нашел этот комментарий: Тип utf8 - это строка байтов utf-8, отформатированная как QByteArray для целей сериализации (в настоящее время размер quint32, за которым следуют байты размера, терминатор отсутствует или не подсчитывается). Я попробую это завтра, 0039..   -  person baler1992    schedule 07.08.2020


Ответы (1)


Короче говоря, протокол wsjtx udp, который я читал, не кодировал строки с использованием типа QDataString, поэтому было неправильно ожидать, что i.readQString() будет работать.

Вместо этого данные были закодированы с использованием QInt32 для определения длины строки, за которой следовали символы UTF8, закодированные в QByteArray.

Я успешно инкапсулировал эту функциональность в функцию:

def jt_decode_utf8_str(i): строки кодируются с помощью int 32, указывающего размер, а затем массив байтов в utf-8 длины size :param i: :return: декодированная строка sz = i.readInt32() b = i.readRawData( sz) вернуть b.decode (utf-8)

person baler1992    schedule 26.08.2020