So, I created a simple binary file using MATLAB that has the following structure:
file.test
--------
[record_type] = 1 % 'int', 4 bytes, record_type = 1 means a string is read next
[string_length] = len(str) % 'int', 4 bytes, tells us how many bytes to read
[string] = '...' % 'char', the number of bytes in string length
[record_type] = 2 % 'int', 4 bytes, record_type = 2 means a vector will be read
[rows] = size(vector,1) % 'int', 4 bytes
[columns] = size(vector,2) % 'int', 4 bytes
[vector] = (vector) % 'double'
I can read this file back in MATLAB with the following code (this is just the read portions of the code, I do have error checking and other things):
fid=fopen('file.test','rb')
record_names={}
record_data=[]
while ~feof(fid)
[record_name_type,count]=fread(fid,1,'int');
if count == 0 % reached eof
break;
end
record_name_length=fread(fid,1,'int');
record_names{end+1}=char(fread(fid,record_name_length,'char')');
% read vector
record_type=fread(fid,1,'int');
rows=fread(fid,1,'int');
cols=fread(fid,1,'int');
record_data{end+1}=fread(fid,[rows,cols],'double');
end
So, I had to translate this same function into Python 2.7. Unfortunately, it's proving to be very difficult. I can't just call fread anymore and tell it how many elements or bytes I want to read. I have tried the following code with structs:
def read_file(filename):
# checking to see if file exists / other checks happen
fid=open(filename,'rb')
record_data=[]
record_names=[]
result=read_record(fid)
while result:
record_names.append(result['record_name'])
record_names.append(result['data'])
result=read_record(fid)
fid.close()
return (record_names, record_data)
def read_record(fid):
try:
# read name
record_name_type = struct.unpack('i',fid.read(struct.calcsize('i')))[0]
record_name_len = struct.unpack('i',fid.read(struct.calcsize('i')))[0]
record_name = struct.unpack('s',fid.read(record_name_len))[0]
# read vector
record_type = struct.unpack('i',fid.read(struct.calcsize('i')))[0]
rows = struct.unpack('i',fid.read(struct.calcsize('i')))[0]
cols = struct.unpack('i',fid.read(struct.calcsize('i')))[0]
record_data = numpy.array(struct.unpack('%dd' % rows,fid.read(rows*struct.calcsize('d'))),dtype=float)
# store into result and return
result=OrderedDict()
result['record_name']=record_name
result['data']=record_data
except struct.error as e:
print e
result=None
return result
Now when running my method in python, I get the following error:
unpack requires a string argument of length 1 which is coming from the except strcut.error as e portion. I had a feeling I was reading the vector incorrectly but I don't know how I'm reading the string incorrectly.
Does anyone know of an easier way to read this binary file? Or is there some tutorial I could follow to help me understand how to properly use structs in Python? I'm really new to it and especially this area in Python.
record_name = struct.unpack('s',fid.read(record_name_len))[0]caused the exception. You should specify the length of string in the format paremeter:'%ds' % record_name_len. - acw1668record_name = struct.unpack('%ds' % record_name_len,fid.read(record_name_len))[0]returns aTypeError: unpack expected 2 arguments, got 3.If I put onlyrecord_name_lenin there, does it just know to useread()? I'm kind of confused D: - Alex