我正在尝试在Python中读取一个二进制文件(代表Matlab中的矩阵)。但是我在读取文件并将字节转换为正确值时遇到麻烦。
二进制文件由一个4字节数字序列组成。前两个数字分别是行数和列数。我的朋友给了我他编写的Matlab函数,该函数使用fwrite来实现。我想做这样的事情:
f = open(filename, 'rb') rows = f.read(4) cols = f.read(4) m = [[0 for c in cols] for r in rows] r = c = 0 while True: if c == cols: r += 1 c = 0 num = f.read(4) if num: m[r][c] = num c += 1 else: break 但是每当我使用f.read(4)时,都会得到类似“ \ x00 \ x00 \ x00 \ x04”的字样(此特定示例应表示4),我无法弄清楚将其转换为正确的数字(使用int,hex或类似的内容无效)。我偶然发现了struct.unpack,但这似乎并没有太大帮助。
这是一个示例矩阵以及Matlab函数为其创建的相应二进制文件(当我使用不带任何大小参数的python函数f.read()读取整个文件时出现)
4 4 2 4 2 2 2 1 3 3 2 4 2 2 6 2 '\x00\x00\x00\x04\x00\x00\x00\x04@\x80\x00\x00@\x00\x00\x00@@\x00\x00@\x00\x00\x00@\x80\x00\x00@\x00\x00\x00@@\x00\x00@\x00\x00\x00@\x00\x00\x00@\x00\x00\x00@\x00\x00\x00@\xc0\x00\x00@\x80\x00\x00?\x80\x00\x00@\x80\x00\x00@\x00\x00\x00' 因此,前4个字节和第5-8个字节都应为4,因为矩阵为4x4。然后应该是4,4,2,4,2,2,2,1,依此类推...
多谢你们!
回答:
因为您之前从未使用过struct ,所以我对您的问题的看法有所提高,因此这是一次很好的学习活动。事实证明,那里有很多曲折-首先,数字不是以4字节整数存储,而是以4字节浮点数(大尾数形式)存储。其次,如果您的示例是正确的,则矩阵未按预期存储-按行存储,而是按列存储。例如,它的输出是这样的(伪代码):
for j in cols: for i in rows: write Aij to file 因此,我必须在阅读后转置结果。这是您需要的示例代码:
import struct def readMatrix(f): rows, cols = struct.unpack('>ii',f.read(8)) m = [ list(struct.unpack('>%df' % rows, f.read(4*rows))) for c in range(cols) ] # transpose result to return return zip(*m) 在这里,我们对其进行测试:
>>> from StringIO import StringIO >>> f = StringIO('\x00\x00\x00\x04\x00\x00\x00\x04@\x80\x00\x00@\x00\x00\x00@@\x00\x00@\x00\x00\x00@\x80\x00\x00@\x00\x00\x00@@\x00\x00@\x00\x00\x00@\x00\x00\x00@\x00\x00\x00@\x00\x00\x00@\xc0\x00\x00@\x80\x00\x00?\x80\x00\x00@\x80\x00\x00@\x00\x00\x00') >>> mat = readMatrix(f) >>> for row in mat: ... print row ... (4.0, 4.0, 2.0, 4.0) (2.0, 2.0, 2.0, 1.0) (3.0, 3.0, 2.0, 4.0) (2.0, 2.0, 6.0, 2.0)
更多&回答...