QDataStream readQString() 如何读取 utf8 字符串

Posted

技术标签:

【中文标题】QDataStream readQString() 如何读取 utf8 字符串【英文标题】:QDataStream readQString() How to read utf8 String 【发布时间】:2020-08-07 07:34:08 【问题描述】:

我正在尝试从使用 Qt 的 QDataStream 方法对数据进行编码的应用程序中解码 UDP 数据包数据,但在尝试解码字符串字段时遇到问题。文档说数据是用 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

有一个状态消息,例如这样的 cmets:

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

收到状态消息时来自套接字的示例数据:

b'\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)

【问题讨论】:

查看了更多文档并发现此评论:“类型 utf8 是格式化为 QByteArray 用于序列化目的的 utf-8 字节字符串(当前 quint32 大小后跟大小字节,不存在终止符或数)。我明天试试这个,0039.. 【参考方案1】:

长话短说,我正在阅读的 wsjtx udp 协议没有使用 QDataString 类型对字符串进行编码,因此期望 i.readQString() 会起作用是错误的。

而是使用 QInt32 对数据进行编码以定义字符串长度,后跟以 QByteArray 编码的 UTF8 字符。

我成功地将这个功能封装在一个函数中:

def jt_decode_utf8_str(i): """ 字符串用 int 32 表示大小进行编码 然后是长度大小为 utf-8 的字节数组 :参数我: :return: 解码后的字符串 """ sz = i.readInt32() b = i.readRawData(sz) 返回 b.decode("utf-8")

【讨论】:

以上是关于QDataStream readQString() 如何读取 utf8 字符串的主要内容,如果未能解决你的问题,请参考以下文章

更正覆盖 QDataStream 运算符和链接问题

QDataStream 未按预期工作

6.5 QDataStream串行化数据流处理

调整 QDataStream

QDataStream和QByteArray

QDataStream 正在变为只读