什么是 Python 中 Matlab 中的“fread”等价物?
Posted
技术标签:
【中文标题】什么是 Python 中 Matlab 中的“fread”等价物?【英文标题】:What is the equivalent of 'fread' from Matlab in Python? 【发布时间】:2011-01-09 21:39:26 【问题描述】:我对 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
在可能很长的情况下如何适合单个字节。
感谢您阅读本文。我希望你能理解我想知道的那种! (任何见解都值得赞赏。)
【问题讨论】:
您可能想考虑拆分问题并将第二部分移动到另一个问题中,标题有点误导。 【参考方案1】:读取一维数组的 Python 代码
在用Python替换Matlab时,我想将二进制数据读入numpy.array
,所以我用numpy.fromfile
将数据读入一维数组:
import numpy as np
with open(inputfilename, 'rb') as fid:
data_array = np.fromfile(fid, np.int16)
与其他 Python 解决方案相比,使用 numpy.fromfile
的一些优势包括:
count=
参数指定它们,但默认为-1
,表示读取整个文件。
能够指定一个打开的文件对象(就像我在上面使用fid
所做的那样)或者你可以指定一个文件名。我更喜欢使用打开的文件对象,但如果您想使用文件名,可以将上面的两行替换为:
data_array = numpy.fromfile(inputfilename, numpy.int16)
二维数组的 Matlab 代码
Matlab 的fread
能够将数据读入[m, n]
形式的矩阵,而不仅仅是将其读入列向量。例如,要将数据读入具有 2 行的矩阵,请使用:
fid = fopen(inputfilename, 'r');
data_array = fread(fid, [2, inf], 'int16');
fclose(fid);
二维数组的等效 Python 代码
您可以使用 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。
【讨论】:
【参考方案2】:来自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() 方法的东西是不行的。
数组实现了序列协议,因此支持与列表相同的操作,但您也可以使用.tolist()
方法从数组创建普通列表。
【讨论】:
不知何故,我在a = array.array('i'), a.fromfile(fid, count)
和numpy.fromfile(fid, numpy.int16)
...33947761、-157220022 与 113、518 之间得到了不同的结果。当我使用 TEXBAT cleanStatic.bin
文件作为 fid (radionavlab.ae.utexas.edu/datastore/texbat).. .什么可以改变以获得相同的结果?【参考方案3】:
真的,我想知道如何复制
[A, count] = fread(fid, 3, 'uint32');
在 Matlab 中,fread()
的签名之一是fread(fileID, sizeA, precision)
。这会读入文件的第一个sizeA
元素(不是字节),每个元素的大小都足以容纳precision
。在这种情况下,由于您正在阅读uint32
,因此每个元素的大小为 32 位或 4 字节。
因此,请尝试使用 io.readline(12)
从文件中获取前 3 个 4 字节元素。
【讨论】:
【参考方案4】:Torsten 的回答涵盖了第一部分...无论如何,您将需要 array
或 numarray
来处理这些数据。
至于 %08X 和 hex2dec 的东西,%08X 只是那些 unit32 数字的打印格式(8 位十六进制,与 Python 完全相同),而 hex2dec('4D445254') 是 0x4D445254 的 matlab。
最后,matlab中的~=是按位比较;在 Python 中使用 ==。
【讨论】:
以上是关于什么是 Python 中 Matlab 中的“fread”等价物?的主要内容,如果未能解决你的问题,请参考以下文章
采用Armjio非精确线搜索求步长的FR非线性共轭梯度法--MATLAB实现
什么是matlab的imadjust在python中的等价物?