Preliminary
I need to read a binary file constructed by writing a Struct to it with Python. So I decided to write a simple wrapper using struct module.
Code
import struct
class structure:
def __init__ ( self, little_endian = True ):
self._little_endian = little_endian
self._table = dict() #stores field name, its format and value
self._pack = list() #stores field names in order fields must be read
def add_field( self, field_name, field_format ):
if field_name in self._table.keys():
print "WARNING :: Field with name '%s' already exists in this structure" % field_name
elif field_format == "":
print "WARNING :: Format cannot be an empty string"
else:
self._table[ field_name ] = { "format" : field_format, "value" : None }
self._pack.append( field_name )
#maybe error handling is required here
def get_value( self, field_name ):
try:
return self._table[ field_name ][ "value" ]
except KeyError:
print "WARNING :: There is no such field named '%s' in this structure" % field_name
return None
def get_format_string( self ):
f_str = ""
for key in self._pack:
f_str += self._table[ key ][ "format" ]
if (self._little_endian == True):
f_str = "<" + f_str
else:
f_str = ">" + f_str
return f_str
def get_size( self ):
return struct.calcsize( self.get_format_string() )
def fill( self, file_ptr ):
result = struct.Struct( self.get_format_string() ).unpack( file_ptr.read( self.get_size() ) )
for (i,key) in enumerate(self._pack):
self._table[ key ][ "value" ] = result[ i ]
def show( self ):
print "General info:"
print "%20s = %s" % ( "Format string", self.get_format_string() )
print "%20s = %d" % ( "Size (bytes)", self.get_size() )
print "Value:"
for key in self._pack:
print "%20s = " % key, self._table[ key ][ "value" ]
Usage
Usage is straightforward. I used the real binary produced by OWON oscilloscope here so some of the values might look strange (consist non-printable characters).
import structure
s = structure.structure( little_endian=True )
s.add_field( "header", "10s" )
s.add_field( "serial", "14s" )
s.add_field( "string", "18s" )
s.add_field( "trig_time", "f" )
s.add_field( "float1", "f" )
s.add_field( "float2", "f" )
with open( "./data/trigger.bin" ) as f:
s.fill( f )
s.show()
Output
General info:
Format string = <10s14s18sfff
Size (bytes) = 54
Value:
header = SPBS01e�
serial = SDS60621715234
string =
trig_time = 99.0
float1 = 3.41239206136e-06
float2 = 0.001953125
As always any suggestions, ideas and critics are appreciated.