MATLAB中的内存映射文件?

Posted

技术标签:

【中文标题】MATLAB中的内存映射文件?【英文标题】:Memory map file in MATLAB? 【发布时间】:2014-01-06 15:12:08 【问题描述】:

我决定使用 memmapfile,因为我的数据(通常为 30Gb 到 60Gb)太大而无法放入计算机的内存中。

我的数据文件包含两列数据,对应于两个传感器的输出,我有 .bin 和 .txt 两种格式。

m=memmapfile('G:\E-Stress Research\Data\2013-12-18\LD101_3\EPS/LD101_3.bin','format','int32')
m.data(1)

我使用上面的代码将我的数据内存映射到变量“m”,但我不知道要使用什么数据格式(int8','int16','int32','int64','uint8',' uint16'、'uint32'、'uint64'、'single' 和 'double')。 事实上,我尝试了 MATLAB 支持的所有列出的数据格式,但是当我使用 m.data(index number) 时,我从来没有得到我所期望的一对数字(2 列数据),这个数字也将是根据我使用的格式而有所不同。

如果有人对 memmapfile 有经验,请帮助我。

Here 是我的数据文件的一些较小版本,因此人们可以了解我的数据的结构:

干杯 詹姆斯

【问题讨论】:

假设你有一个普通的二进制文件,没有结构。所有的数据都简单的写成一行,类似于X(:)将矩阵转换为向量。你有任何信息如何编写二进制文件吗?如果没有,请尝试创建小示例 .txt 和 .bin 文件并上传。 看来使用'Format' 选项可以指定“数组形状”。 @DanielR 我不知道二进制文件是怎么写的,但是我创建了一些相对较小的文件并上传了它们:dropbox.com/sh/rzut4zbrert9fm0/q9SiZYmrdG @A.Donda 我认为定义数组形状的问题是我有两列数据但长度未知;这还能用吗? 使用常规数据时,如果数据大小未知,可以使用reshape(data,2,[])[] 是一个占位符,表示使用任何适合的函数,' 中可能有类似的选项格式化函数 【参考方案1】:

memmapfile 是为读取二进制文件而设计的,这就是您在处理文本文件时遇到问题的原因。那里的数据是字符,因此您必须将它们作为字符读取,然后将它们解析为数字。更多内容如下。

二进制文件似乎不仅仅包含以二进制格式写入的浮点值流。我也在文件中看到标识符(字符串)和其他内容。您阅读该文件的唯一希望是联系创建二进制文件的设备制造商,并询问他们如何读取此类文件。可能会有一个 SDK,或者至少是格式的描述。您可能需要对此进行调查,因为您的文本文件中的浮点数可能会被截断,也就是说,与直接读取浮点数的二进制表示相比,您会丢失精度。

好的,那么如何使用memmapfile 读取您的文件? This post 提供了一些提示。

首先我们以'uint8' 的形式打开您的文件(注意没有'char' 选项,因此作为一种解决方法,我们将文件内容读入相同大小的数据类型):

m = memmapfile('RTL5_57.txt','Format','uint8'); % uint8 is default, you could leave that off

我们可以通过将读取的数据转换为 char 来将读取的 uint8 数据渲染为字符:

c = char(m.Data(1:19)).' % read the first three lines. NB: transpose just for getting nice output, don't use it in your code
c = 
    0.398516    0.063440
    0.399611    0.063284
    0.398985    0.061253

由于文件中的每一行都具有相同的长度(数字为 2*8 个字符,换行符为 1 个制表符,换行符为 2 个字符 = 19 个字符),我们可以通过读取 N*19 值从文件中读取 N 行.所以m.Data(1:19) 给你第一行,m.Data(20:38) 第二行,m.Data(20:57) 第二和第三行。一次读多少就读多少。

然后我们必须将读入的数据解析成浮点数:

f = sscanf(c,'%f')
f =
    0.3985
    0.0634
    0.3996
    0.0633
    0.3990
    0.0613

现在剩下的就是将它们重塑为两列格式

d = reshape(f,2,[]).'
d =
    0.3985    0.0634
    0.3996    0.0633
    0.3990    0.0613

比使用memmapfile更简单的方法: 您不需要使用memmapfile 来解决您的问题,而且我认为这会使事情变得更加复杂。您可以简单地使用fopen 后跟fread

fid = fopen('RTL5_57.txt');
c = fread(fid,Nlines*19,'*char');
% now sscanf and reshape as above
% NB: one can read the values the text file directly with f = fscanf(fid,'%f',Nlines*19).
% However, in testing, I have found calling fread followed by sscanf to be faster
% which will make a significant difference when reading such large files.

使用它,您可以一次读取Nlines 值对,处理它们,然后再次调用fread 以读取下一个Nlinesfread 记住它在文件中的位置(就像 fscanf 一样),所以只需使用相同的调用来获取下一行。因此很容易编写一个循环来处理整个文件,如果您在文件末尾,请使用feof(fid) 进行测试。

建议使用更简单的方法here:使用textscan。稍微修改他们的示例代码:

Nlines = 10000;

% describe the format of the data
% for more information, see the textscan reference page
format = '%f\t%f';

fid = fopen('RTL5_57.txt');

while ~feof(fid)
   C = textscan(fid, format, Nlines, 'CollectOutput', true);
   d = C1;  % immediately clear C at this point if you need the memory! 
   % process d
end

fclose(fid);

再次注意,fread 后跟 sscanf 将是最快的。但是请注意,只要文本文件中有一行与您的格式不完全匹配,fread 方法就会终止。另一方面,textscan 可以容忍空白更改,因此更加健壮。

【讨论】:

以上是关于MATLAB中的内存映射文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何将文件映射到内存?

有没有办法/工具来显示系统中的所有内存映射文件?

读取内存内存映射文件 C++ 和 C#

SQL Server 复制中的内存映射文件写入失败

Linux 内核 内存管理内存映射相关数据结构 ⑥ ( 文件映射 虚拟内存区域 | vm_area_struct | vm_operations_struct | 匿名映射 虚拟内存区域 )

windows文件映射