微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

根据 uint32 id 解析 x 长度块中的流

如何解决根据 uint32 id 解析 x 长度块中的流

我几乎没有 C/Qt 经验,并且有一个需要移植到 Python 的小型解析器。有没有人能够解释我如何在 Python 中实现以下内容?我明白结果是什么,只是无法理解如何实现 uint32 实例化和基于 4 字节“id”导致不同部分长度的移位。我希望只使用本机 Python 3.5+ 包来解析它,numpy 或类似的包如果它使输入方便的话就可以了。

QDataStream stream(item);
stream.setByteOrder(QDataStream::LittleEndian);
Items parts;
while (!stream.atEnd()) {
    quint32 partId;
    stream >> id;
    char *bytes;
    uint length;
    stream.readBytes(bytes,length);
    parts.append(QPair<quint32,QByteArray>(id,QByteArray(bytes,length)));
    delete bytes;
}
return parts;

解决方法

由于在 python 中数字类型与 C++ 的数字类型不匹配,因此 QDataStream 不再使用“>>”运算符来获取值,而是具有特定的方法,例如 readUInt32。

考虑以下生成数据的代码:

#include <QDataStream>
#include <QFile>
#include <QDebug>

int main()
{
    QFile file("file.dat");
    if(!file.open(QIODevice::WriteOnly)){
        qDebug() << file.error() << file.errorString();
        return EXIT_FAILURE;
    }
    QDataStream stream(&file);
    stream.setByteOrder(QDataStream::LittleEndian);
    stream.setVersion(QDataStream::Qt_5_15);

    QVector <QPair<quint32,QByteArray>> data;
    data.append({1,"One"});
    data.append({2,"Two"});
    data.append({3,"Three"});

    for(const QPair<quint32,QByteArray> & d: qAsConst(data)){
        stream << d.first;
        stream.writeBytes(d.second.constData(),d.second.size());
    }
    return EXIT_SUCCESS;
}

以下代码获取数据:

import sys

from PyQt5.QtCore import QByteArray,QDataStream,QFile,QIODevice


file = QFile("file.dat")
if not file.open(QIODevice.ReadOnly):
    print(file.error(),file.errorString())
    sys.exit(-1)

items = []

stream = QDataStream(file)
stream.setByteOrder(QDataStream.LittleEndian)
stream.setVersion(QDataStream.Qt_5_15)
while not stream.atEnd():
    id_ = stream.readUInt32()
    data = stream.readBytes()
    items.append((id_,QByteArray(data)))
print(items)

输出:

[(1,PyQt5.QtCore.QByteArray(b'One')),(2,PyQt5.QtCore.QByteArray(b'Two')),(3,PyQt5.QtCore.QByteArray(b'Three'))]

如果使用 PySide2,则实现会有所改变。

import sys

from PySide2.QtCore import QByteArray,file.errorString())
    sys.exit(-1)

items = []

stream = QDataStream(file)
stream.setByteOrder(QDataStream.LittleEndian)
stream.setVersion(QDataStream.Qt_5_15)
while not stream.atEnd():
    id_ = stream.readUInt32()
    data = QByteArray()
    stream >> data
    items.append((id_,data))
print(items)

输出:

[(1,PySide2.QtCore.QByteArray(b'One')),PySide2.QtCore.QByteArray(b'Two')),PySide2.QtCore.QByteArray(b'Three'))]

更新:

如果不使用QDataStream是无法获取数据的,因为Qt对每种类型的数据都使用自己的格式,而且这种格式不是一个标准,可以随版本变化而不通知它。为此,必须指明所使用的 QDataStream 的字节顺序和版本。

更新 2

假设 QDataStream 用来打包 quint32 和字节的格式是 QDataStream.Qt_5_15 那么一个可能的实现是:

import sys
import struct

items = []

with open("file.dat","rb") as f:
    while True:
        try:
            (id_,) = struct.unpack("I",f.read(4))
            (length,f.read(4))
            data = f.read(length)
        except (EOFError,struct.error) as e:
            break
        else:
            items.append((id_,data))

print(items)

输出:

[(1,b'One'),b'Two'),b'Three')]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。