我几乎不了解Matlab,需要将一些解析例程转换为Python。它们适用于大型文件,它们本身被分为“块”,而且我从文件顶部的校验和开始就有困难。
Matlab到底发生了什么?
status = fseek(fid, 0, 'cof');
fposition = ftell(fid);
disp(' ');
disp(['** Block ',num2str(iBlock),' File Position = ',int2str(fposition)]);
% ----------------- Block Start ------------------ %
[A, count] = fread(fid, 3, 'uint32');
if(count == 3)
magic_l = A(1);
magic_h = A(2);
block_length = A(3);
else
if(fposition == file_length)
disp(['** End of file OK']);
else
disp(['** Cannot read block start magic ! Note File Length = ',num2str(file_length)]);
end
ok = 0;
break;
end
fid是当前正在查看的文件 iBlock是一个计数器,你在文件中“阻止”
magic_l和magic_h稍后与校验和有关,这里是代码(直接来自上面的代码):
disp(sprintf(' Magic_L = %08X, Magic_H = %08X, Length = %i', magic_l, magic_h, block_length));
correct_magic_l = hex2dec('4D445254');
correct_magic_h = hex2dec('43494741');
if(magic_l ~= correct_magic_l | magic_h ~= correct_magic_h)
disp(['** Bad block start magic !']);
ok = 0;
return;
end
remaining_length = block_length - 3*4 - 3*4; % We read Block Header, and we expect a footer
disp(sprintf(' Remaining Block bytes = %i', remaining_length));
%08X
和hex2dec
的内容是怎么回事? 3*4
而不是12
?实际上,我想知道如何在Python中复制[A, count] = fread(fid, 3, 'uint32');
,因为io.readline()
只是拉动文件的前3个字符。如果我在这里错过了某点,我会道歉。只是在文件上使用io.readline(3)
似乎返回了它不应该返回的内容,并且我不明白block_length
如果可能在很长的时间内如何适合单个字节。
感谢您阅读此漫步。我希望你能理解我想知道的一切! (任何见解都值得赞赏。)
答案 0 :(得分:10)
当用Python替换Matlab时,我想将二进制数据读入numpy.array
,所以我使用numpy.fromfile
将数据读入一维数组:
import numpy as np
with open(inputfilename, 'rb') as fid:
data_array = np.fromfile(fid, np.int16)
使用numpy.fromfile
与其他Python解决方案相比的一些优点包括:
count=
参数指定它们,但默认为-1
,表示读取整个文件。能够指定一个打开的文件对象(就像我上面用fid
所做的那样),或者你可以指定一个文件名。我更喜欢使用打开的文件对象,但是如果你想使用文件名,你可以用上面的两行替换:
data_array = numpy.fromfile(inputfilename, numpy.int16)
Matlab的fread
能够将数据读入格式为[m, n]
的矩阵,而不是仅将其读入列向量。例如,要将数据读入具有2行的矩阵,请使用:
fid = fopen(inputfilename, 'r');
data_array = fread(fid, [2, inf], 'int16');
fclose(fid);
您可以使用Numpy的shape
和transpose
在Python中处理此方案。
import numpy as np
with open(inputfilename, 'rb') as fid:
data_array = np.fromfile(fid, np.int16).reshape((-1, 2)).T
-1
告诉numpy.reshape
根据另一个维度推断该维度的数组长度 - 相当于Matlab的inf
无穷大表示。.T
转换数组,使其成为一个二维数组,第一个维度 - 轴 - 长度为2. 答案 1 :(得分:7)
从documentation of fread
开始,它是一个读取二进制数据的函数。第二个参数指定输出向量的大小,第三个参数指定读取的项目的大小/类型。
为了在Python中重新创建它,您可以使用array
模块:
f = open(...)
import array
a = array.array("L") # L is the typecode for uint32
a.fromfile(f, 3)
这将读取文件f
中的三个uint32值,这些值在a
之后可用。来自fromfile
的文档:
从文件对象f中读取n个项目(作为机器值),并将它们附加到数组的末尾。如果少于n个项目可用,则会引发EOFError,但可用的项目仍会插入到阵列中。 f必须是一个真正的内置文件对象;使用read()方法的其他东西不会。
Arrays实现了序列协议,因此支持与列表相同的操作,但您也可以使用.tolist()
方法从数组中创建普通列表。
答案 2 :(得分:2)
但实际上,我想知道如何复制
[A, count] = fread(fid, 3, 'uint32');
在Matlab中,fread()
的一个签名是fread(fileID, sizeA, precision)
。这将读取文件的第一个sizeA
元素(不是字节),每个元素的大小都足以容纳precision
。在这种情况下,由于您正在读取uint32
,因此每个元素的大小为32位或4个字节。
因此,请尝试io.readline(12)
从文件中获取前3个4字节元素。
答案 3 :(得分:0)
Torsten的回答涵盖了第一部分......无论如何,您将需要array
或numarray
对此数据执行任何操作。
对于%08X和hex2dec的东西,%08X只是那些unit32号码的打印格式(8位十六进制,与Python完全相同),而hex2dec('4D445254')是matlab for 0x4D445254。
最后,〜=在matlab中是一个按位比较;在Python中使用==。