BlackJack hat geschrieben:Gibt es bei struct irgend einen Automatismuss für mein read_variable_String()? Ich hab was gelesen von einem "Pascal string", aber ich hab's nicht geschafft das richtig einzusetzten...
Zeichenketten in Pascal (also im "Original") konnten maximal 255 Zeichen lang sein, weil die so im Speicher abgelegt wurden, dass das erste Byte die Länge angegeben hat. In der CRID-Beschreibung ist die Längenangabe aber 4 Bytes lang.
Also dann gehe ich davon aus, das es keine automatische Auswertung für Strings mit Längenangabe von 4 Bytes gibt?
Ich habe die Methode
read_variable_String() nochmal umgeschrieben, sodas nicht direkt aus dem File-Objekt der String mit .read( X ) ausgelesen wird, sondern auch mit struct.unpack() wobei das Format dann die länge des Strings beinhaltet, also string_length + "s"
BlackJack hat geschrieben:Zurück zu Deinem Programm: Der Sinn, das `unpack()` ein Tupel liefert ist eigentlich, dass man eine längere Format-Zeichenkette angibt und mehr als einen Wert auf einmal dekodiert.
Dafür konnte ich mir aber keine einfache Beschreibung der Binär-Daten ausdenken, also wie die Daten Aufgebaut sind...
Hier mal mein bisheriger Stand:
StructUnpacker.py
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import struct
class StructUnpacker:
"""
Allgemeine Klasse zum einlesen von Binärdaten
Bsp.:
su = StructUnpacker.StructUnpacker( fileObj, byteorder=">" )
su.read( "i", "CRID-Version" )
su.read( "q", "CRID-ID" )
su.read( "h", "protected flag" )
su.read_variable_String( "crid title" )
print su.dumpdata()
"""
def __init__( self, fileObj, byteorder ):
self.fileObj = fileObj
self.byteorder = byteorder
self.data = {}
##################################################################
def read( self, Ctype, item ):
"""
Einlesen eines Zeichen
"""
self.data[item] = self._readitem( Ctype )
def read_variable_String( self, item ):
"""
Einlesen eines Textes von variabler Länge.
Dabei wird erst die Anzahl der Text-Länge eingelesen, danach der
eigentliche Text.
"""
string_length = self._readitem( "i" )
self.data[item] = self._readitem( "%ss" % string_length )
#~ self.data[item] = self.fileObj.read( string_length ).strip()
#-----------------------------------------------------------------
def _readitem( self, Ctype ):
"""
lesen eines Zeichens aus dem File-Objekt
wird von read() und read_variable_String() gleichzeitig genutzt
"""
size = struct.calcsize( Ctype )
fmt = self.byteorder + Ctype
return struct.unpack( fmt, self.fileObj.read( size ) )[0]
##################################################################
def __getitem__( self, key ):
"""
Liefert einen gespeicherten Eintrag anhand des Key's zurück
"""
return self.data[key]
##################################################################
def dump( self ):
print "="*80
print ">>> dump [%s]" % self.fileObj.name
for k,v in self.data.iteritems():
print "%s: %s" % (k,v)
print "="*80
Der Aufbau der Binärdatei ist in einer einfache Funktion festgehalten, diese Ließt die Datei aus und liefert die StructUnpacker-Instanz zurück, mit der man dann die Daten abfragen kann:
Code: Alles auswählen
import StructUnpacker
def parse( fileObj ):
"""
Verarbeitet eine CRID-Datei der M740AV-DVB-Box
"""
su = StructUnpacker.StructUnpacker( fileObj, byteorder=">" )
su.read( "i", "CRID-Version" )
su.read( "q", "CRID-ID" )
su.read( "i", "Recording-State" )
su.read( "i", "epg start time" )
su.read( "i", "epg end time" )
su.read( "i", "user access data" )
su.read( "i", "rec pre-offset" )
su.read( "i", "rec post-offset" )
su.read( "i", "rec type" )
su.read( "i", "series ID" )
su.read( "h", "protected flag" )
su.read_variable_String( "crid title" )
su.read( "i", "pieces" )
su.read_variable_String( "rec control file" )
su.read( "i", "absolute rec start time" )
su.read( "q", "start-timestamp" )
su.read( "q", "end-timestamp" )
su.read_variable_String( "epg short text" )
su.read_variable_String( "epg long text" )
su.read( "i", "series ID" )
return su
BlackJack hat geschrieben:Wenn das ganze portabel sein soll, dann solltest Du "big endian" explizit vorgeben.
Das verstehe ich nicht ganz... Ich dachte ehr, ich wäre Variabler, wenn man die byteorder frei wählen kann. Also ich erzeuge die Binär Dateien nicht selber, diese produziert die Box ja selber. Was ich mir allerdings vorstellen könnte, das ich irgendwann vielleicht die Dateien editieren möchte... (Wobei ich dabei nciht weiß wie ich anfangen würde)