2016-09-13 2 views
2

Ich habe eine binäre Datei mit folgendem Format:Lesen von Daten aus Binärdatei Python

enter image description here

und ich verwende diesen Code um es zu öffnen:

import numpy as np 

f = open("author_1", "r") 

dt = np.dtype({'names': ['au_id','len_au_name','au_name','nu_of_publ', 'pub_id', 'len_of_pub_id','pub_title','num_auth','len_au_name_1', 'au_name1','len_au_name_2', 'au_name2','len_au_name_3', 'au_name3','year_publ','num_of_cit','citid','len_cit_tit','cit_tit', 'num_of_au_cit','len_cit_au_name_1','au_cit_name_1', len_cit_au_name_2', 
'au_cit_name_2','len_cit_au_name_3','au_cit_name_3','len_cit_au_name_4', 
'au_cit_name_4', 'len_cit_au_name_5','au_cit_name_5','year_cit'], 
     'formats': [int,int,'S13',int,int,int,'S61',   int,int,'S8',int,'S7',int,'S12',int,int,int,int,'S50',int,int, 
       'S7',int,'S7',int,'S9',int,'S8',int,'S1',int]}) 
a = np.fromfile(f, dtype=dt, count=-1, sep="") 

Und ich nehme dies:

array([ (1, 13, b'Scott Shenker', 200, 1, 61, b'Integrated services in the internet architecture: an overview', 3, 8, b'R Braden', 7, b'D Clark', 12, b'S Shenker\xe2\x80\xa6', 1994, 1000, 401, 50, b'[HTML] An architecture for differentiated services', 5, 7, b'D Black', 7, b'S Blake', 9, b'M Carlson', 8, b'E Davies', 1, b'Z', 1998), 
(402, 72, b'Resource rese', 1952544370, 544108393, 1953460848, b'ocol (RSVP)--Version 1 functional specification\x05\x00\x00\x00\x08\x00\x00\x00R Brad', 487013, 541851648, b'Zhang\x08', 1109414656, b'erson\x08', 542310400, b'Herzog\x07\x00\x00\x00S ', 1768776010, 511342, 103168, 22016, b'\x00A reliable multicast framework for light-weight s', 1769173861, 544435823, b'and app', 1633905004, b'tion le', 543974774, b'framing\x04', 458752, b'\x00\x00S Floy', 2660, b'', 1632247894), 

Eine Idee, wie die ganze Datei geöffnet werden kann?

+0

Zur Klarstellung: Sie wissen, wie der erste Datensatz aus der Datei zu lesen und Sie wollen in der Lage sein zu lesen alle Aufzeichnungen? –

+3

Verwenden Sie stattdessen Pythons Standardmethoden zum Lesen von Dateien und das Modul 'struct'. – Phillip

+0

Beachten Sie, dass Sie zum Lesen des dritten Elements (Autorenname) und * alles darüber hinaus * das zweite Element lesen und diese Länge dynamisch verwenden müssen. Momentan hast du es fest programmiert, was sehr schlecht ist - du wirst einen komplizierteren dynamischen Reader erstellen müssen, nur die Verwendung von numpy wird niemals funktionieren. – Ajean

Antwort

0

Ich stimme Ryan zu: das Parsen der Daten ist einfach, aber nicht trivial und wirklich mühsam. Wieviel Speicherplatz Sie auch sparen, wenn Sie die Daten auf diese Weise packen, Sie zahlen es zum Zeitpunkt des Auspackens teuer.

Wie auch immer, die Datei besteht aus Datensätzen und Feldern variabler Länge. Jeder Datensatz besteht aus einer variablen Anzahl und Länge von Feldern, die wir in Byte-Blöcken lesen können. Jeder Chunk wird ein anderes Format haben. Du hast die Idee. Folgt man dieser Logik, montiert ich diese drei Funktionen, dass Sie fertig sind, ändern, testen, etc:

from struct import Struct 
import struct 

def read_chunk(fmt, fileobj): 
    chunk_struct = Struct(fmt) 
    chunk = fileobj.read(chunk_struct.size) 
    return chunk_struct.unpack(chunk) 

def read_record(fileobj): 
    author_id, len_author_name = read_chunk('ii', f) 
    author_name, nu_of_publ = read_chunk(str(len_author_name)+'ci', f) # 's' or 'c' ? 
    record = { 'author_id': author_id, 
       'author_name': author_name, 
       'publications': [] } 
    for pub in range(nu_of_publ): 
     pub_id, len_pub_title = read_chunk('ii', f) 
     pub_title, num_pub_auth = read_chunk(str(len_pub_title)+'ci', f) 
     record['publications'].append({ 
       'publication_id': pub_id, 
       'publication_title': pub_title, 
       'publication_authors': [] }) 
     for auth in range(num_pub_auth): 
      len_pub_auth_name = read_chunk('i', f) 
      pub_auth_name = read_chunk(str(len_pub_auth_name)+'c', f) 
      record['publications']['publication_authors'].append({'name': pub_auth_name}) 
     year_publ, nu_of_cit = read_chunk('ii', f) 
     # Finish building your record with the remaining fields... 
     for cit in range(nu_of_cit): 
      cit_id, len_cit_title = read_chunk('ii', f) 
      cit_title, num_cit_auth = read_chunk(str(len_cit_title)+'ci', f) 
     for cit_auth in range(num_cit_auth): 
      len_cit_auth_name = read_chunk('i', f) 
      cit_auth_name = read_chunk(str(len_cit_auth_name)+'c', f) 
     year_cit_publ = read_chunk('i', f) 
    return record 

def parse_file(filename): 
    records = [] 
    with open(filename, 'rb') as f: 
     while True: 
      try: 
       records.append(read_record(f)) 
      except struct.error: 
       break 
    # do something useful with the records... 
+0

ich habe es getestet und nehme dieses Ergebnis: AttributeError: Typ Objekt 'Struct' hat kein Attribut 'Fehler'. Irgendeine Idee was falsch ist – lefbar

+0

es gelesen falsche Zahlen für pub_id und len_pub_titlte – lefbar

+0

Sie benötigen eine 'import struct 'am Anfang auch. – chapelo

0

Die in dieser Datei gespeicherte Datenstruktur ist hierarchisch und nicht "flach": Untergeordnete Arrays unterschiedlicher Länge werden in jedem übergeordneten Element gespeichert. Es ist nicht möglich, eine solche Datenstruktur mit numpy arrays (even recarrays) darzustellen, daher ist es nicht möglich, die Datei mit np.fromfile() zu lesen.

Was meinen Sie mit "Öffnen Sie die ganze Datei"? Mit welcher Art von Python-Datenstruktur möchten Sie enden?

Es wäre einfach, aber immer noch nicht trivial, eine Funktion zu schreiben, um die Datei in eine Liste von Wörterbüchern zu zerlegen.