如何使用QDataStream在Python中打开bin文件 [英] How to open a bin file in Python using QDataStream

查看:168
本文介绍了如何使用QDataStream在Python中打开bin文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个bin文件,该文件已在需要访问并转换为csv文件的应用程序中编码.我已经获得了文档,但是不确定如何在Python中访问此文件的内容.

I've got a bin file that was encoded in an application that I need to get access to and convert to a csv file. I've been given the documentation, but am not sure how to access the contents of this file in Python.

以下是有关数据集如何序列化的一些详细信息

Here are some of the details about how the dataset was serialized

Datasets.bin是使用Qt的QDataStream序列化版本QDataStream :: Qt_4_7序列化的DataSet类的列表.

Datasets.bin is a list of DataSet classes serialized using Qt's QDataStream serialization using version QDataStream::Qt_4_7.

The format of the datasets.bin file is:

quint32 Magic Number    0x46474247
quint32 Version     1
quint32 DataSet Marker  0x44415441
qint32      # of DataSets       n
DataSet DataSet 1
DataSet DataSet 2
     .
     .
     .
     .
DataSet DataSet n


The format of each DataSet is:

quint32     Magic Number    0x53455455  
QString     Name
quint32     Flags           Bit field (Set Table)
QString     Id          [Optional]  
QColor      Color           [Optional]
qint32          Units           [Optional]
QStringList         Creator Ids     [Optional]
bool            Hidden          [Optional]
QList<double>   Thresholds      [Optional]
QString         Source          [Optional]
qint32          Role            [Optional]
QVector<QPointF>    data points

我一直在研究PyQt4数据流文档,但是我似乎找不到任何特定的示例.向我指出正确方向的任何帮助都会很棒

I've been looking in to the PyQt4 datastream documentation, but I can't seem to find any specific examples. Any help pointing me in the right direction would be great

推荐答案

PyQt无法以与C ++中相同的方式读取所有数据,因为它无法处理模板类(例如QList<double>QVector<QPointF>),这会需要Python所不具备的特定语言支持.这意味着必须使用解决方法.幸运的是,数据流格式非常简单,因此可以读取任意模板类简化为简单的算法:将长度读取为uint32,然后在range上进行迭代,然后将包含的元素逐一读取到list中:

PyQt cannot read all of the data the same way as in C++, because it cannot handle template classes (like QList<double> and QVector<QPointF>), which would require language-specific support that is not available in Python. This means a work-around must be used. Fortunately, the datastream format is quite straightforward, so reading arbitrary template classes can be reduced to a simple algorithm: read the length as a uint32, then iterate over a range and read the contained elements one-by-one into a list:

points = []
length = stream.readUInt32()
for index in range(length):
    point = QPoint()
    stream >> point
    points.append(point)

下面是一个脚本,该脚本显示了如何正确读取整个数据集格式:

Below is a script that shows how to read the whole dataset format correctly:

from PyQt4 import QtCore, QtGui

FLAG_HASSOURCE = 0x0001
FLAG_HASROLE = 0x0002
FLAG_HASCOLOR = 0x0004
FLAG_HASID = 0x0008
FLAG_COMPRESS = 0x0010
FLAG_HASTHRESHOLDS = 0x0020
FLAG_HASUNITS = 0x0040
FLAG_HASCREATORIDS = 0x0080
FLAG_HASHIDDEN = 0x0100
FLAG_HASMETADATA = 0x0200

MAGIC_NUMBER = 0x46474247
FILE_VERSION = 1
DATASET_MARKER = 0x44415441
DATASET_MAGIC = 0x53455455

def read_data(path):
    infile = QtCore.QFile(path)
    if not infile.open(QtCore.QIODevice.ReadOnly):
        raise IOError(infile.errorString())

    stream = QtCore.QDataStream(infile)
    magic = stream.readUInt32()
    if magic != MAGIC_NUMBER:
        raise IOError('invalid magic number')
    version = stream.readUInt32()
    if version != FILE_VERSION:
        raise IOError('invalid file version')
    marker = stream.readUInt32()
    if marker != DATASET_MARKER:
        raise IOError('invalid dataset marker')
    count = stream.readInt32()
    if count < 1:
        raise IOError('invalid dataset count')

    stream.setVersion(QtCore.QDataStream.Qt_4_7)

    rows = []
    while not stream.atEnd():
        row = []

        magic = stream.readUInt32()
        if magic != DATASET_MAGIC:
            raise IOError('invalid dataset magic number')

        row.append(('Name', stream.readQString()))

        flags = stream.readUInt32()
        row.append(('Flags', flags))

        if flags & FLAG_HASID:
            row.append(('ID', stream.readQString()))
        if flags & FLAG_HASCOLOR:
            color = QtGui.QColor()
            stream >> color
            row.append(('Color', color))
        if flags & FLAG_HASUNITS:
            row.append(('Units', stream.readInt32()))
        if flags & FLAG_HASCREATORIDS:
            row.append(('Creators', stream.readQStringList()))
        if flags & FLAG_HASHIDDEN:
            row.append(('Hidden', stream.readBool()))
        if flags & FLAG_HASTHRESHOLDS:
            thresholds = []
            length = stream.readUInt32()
            for index in range(length):
                thresholds.append(stream.readDouble())
            row.append(('Thresholds', thresholds))
        if flags & FLAG_HASSOURCE:
            row.append(('Source', stream.readQString()))
        if flags & FLAG_HASROLE:
            row.append(('Role', stream.readInt32()))

        points = []
        length = stream.readUInt32()
        for index in range(length):
            point = QtCore.QPointF()
            stream >> point
            points.append(point)
        row.append(('Points', points))
        rows.append(row)

    infile.close()

    return rows

rows = read_data('datasets.bin')

for index, row in enumerate(rows):
    print('Row %s:' % index)
    for key, data in row:
        if isinstance(data, list) and len(data):
            print('  %s = [%s ... ] (%s items)' % (
                  key, repr(data[:3])[1:-1], len(data)))
        else:
            print('  %s = %s' % (key, data))

这篇关于如何使用QDataStream在Python中打开bin文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆