2016-11-22 7 views
2

액세스 권한을 얻고 csv 파일로 변환해야하는 응용 프로그램에 인코딩 된 bin 파일이 있습니다. 나는 문서를 받았지만 파이썬에서이 파일의 내용에 접근하는 방법을 모르겠습니다.QDataStream을 사용하여 Python에서 bin 파일을 여는 방법

다음은 데이터 세트가

Datasets.bin 연재 데이터 집합 클래스의 목록 버전 QDataStream를 사용하여 Qt의 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 데이터 스트림 문서에 찾아 봤는데,하지만 난 어떤 구체적인 예를 찾을 수 없습니다. 올바른 방향으로 나를 가리키는 도움이 될 것입니다

+0

하는 것이, 예를 QDataStream를 사용하는 것이 가장 쉬운 방법이 될 것이다 :

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

스크립트의 수정 된 버전입니다 Qt 파이썬 바인딩? –

+0

https://dl.dropboxusercontent.com/u/28824868/datasets.bin 누구나 테스트하려는 경우 데이터 세트 파일에 대한 링크입니다. –

+0

@MichaelBawol. 나는 그 파일을 C++로 읽으려고했는데 첫 번째'Source' 엔트리에서 실패했다. 따라서 형식이 불완전하거나 잘못되었거나 파일이 손상되었습니다. 파일을 어디서 가져 왔니? 알려진 값을 가진 작은 장난감 예가 있습니까? – ekhumoro

답변

1

다음은 데이터 집합 형식을 올바르게 읽는 방법을 보여주는 스크립트입니다.

그러나 현재 실제로 모든 데이터를 올바르게 읽을 수는 없습니다. 이는 QList<double>QVector<QPointF> 템플릿 클래스로, PyQt는 직접 지원하지 않습니다. 코드에서이 타입을 읽는 데 필요한 누락 된 PyQt 메소드 대신 readQVariantList을 사용했습니다.

UPDATE는 :

나는이 작업을 수행 할 수있는 방법이 없다는 author of PyQt confirmed을 PyQt는 메일 링리스트에서 임의의 템플릿 클래스 처리에 대해 질문합니다. 그래서 유일한 옵션은 C++에서 일종의 변환 도구를 작성하는 것입니다.

UPDATE2 :

그것은 내가 지금 해결 방법을 발견했기 때문에 나는, 너무 빨리 말 것. datastream format은 내가 생각했던 것보다 훨씬 간단하며 임의의 템플릿 클래스를 읽는 것이 간단한 알고리즘으로 줄일 수 있습니다. 기본적으로 길이를 uint32으로 읽어 들인 다음 range을 반복하고 포함 된 요소를 하나씩 읽습니다. list :

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)) 
+0

"PyQt가 C++ 템플릿 클래스를 직접 지원할 수 없기 때문에 QList 또는 QVector 을 읽을 수 있는지 여부를 알지 못합니다." - 나는 이것이 스스로 좋은 질문이라고 생각한다. – Trilarion

+0

다소 효과가 있습니다. 내용에 액세스하고 일부 정보를 행 목록에 추가했습니다. 이 정보는 드물기는하지만 파일 자체가 없으면 어떻게 어려울 지 알 수 있습니다. 나는 그것을 위에 포함시켰다. 나는이 코드를 더 잘 이해하기 위해 아직 파고 들고있다. –