在 MAT 文件中保存和加载部分变量
您可以在 MAT 文件中直接保存和加载部分变量,而无需使用 matfile
函数将其加载到内存中。相对于 load
或 save
函数,使用 matfile
函数的主要优点是对于太大而无法装入内存中的数据集,可以仅处理该数据集的一部分。当处理这些大型变量时,应一次将尽可能多的数据读取和写入到内存中。否则,重复的文件访问会严重降低代码的性能。
使用 matfile
函数保存和加载
此示例说明如何使用 matfile
函数在现有 MAT 文件中加载、修改和保存变量的一部分。
创建具有两个变量 A
和 B
的 7.3 版 MAT 文件。
A = rand(5); B = magic(10); save example.mat A B -v7.3; clear A B
基于 MAT 文件 example.mat
构造一个 MatFile
对象。matfile
函数创建一个对应于 MAT 文件的 MatFile
对象,并包含 MatFile
对象的属性。默认情况下,matfile
仅允许从现有 MAT 文件加载。
exampleObject = matfile('example.mat');
要启用保存,请使用 Writable
参数调用 matfile
。
exampleObject = matfile('example.mat','Writable',true);
或者,构造该对象并在单独的步骤中设置 Properties.Writable
。
exampleObject = matfile('example.mat');
exampleObject.Properties.Writable = true;
将 B
的第一行从 example.mat
加载到变量 firstRowB
中,并修改数据。当索引与 7.3 版的 MAT 文件关联的对象时,MATLAB® 仅加载所指定的变量部分。
firstRowB = exampleObject.B(1,:); firstRowB = 2 * firstRowB;
使用存储在 firstRowB
中的值更新 example.mat
中变量 B
的第一行中的值。
exampleObject.B(1,:) = firstRowB;
对于非常大的文件,最佳做法是应一次将尽可能多的数据读取和写入到内存中。否则,重复的文件访问会严重影响代码的性能。例如,假设文件包含许多行和列,并且加载一行就需要占用大部分可用内存。这种情况下不要一次更新一个元素,而应该更新一行。
[nrowsB,ncolsB] = size(exampleObject,'B'); for row = 1:nrowsB exampleObject.B(row,:) = row * exampleObject.B(row,:); end
如果内存大小不是问题,则可以一次更新一个变量的完整内容。
exampleObject.B = 10 * exampleObject.B;
或者,通过使用 -append
选项调用 save
函数来更新变量。-append
选项要求 save
函数仅替换指定的变量 B
,并保留文件中的其他变量不变。此方法始终要求您加载并保存整个变量。
load('example.mat','B'); B(1,:) = 2 * B(1,:); save('example.mat','-append','B');
使用 matlab.io.MatFile
对象向文件中添加变量。
exampleObject.C = magic(8);
还可以通过使用 -append
选项调用 save
函数来添加变量。
C = magic(8); save('example.mat','-append','C'); clear C
动态加载部分变量
此示例说明如何动态地从 MAT 文件访问部分变量。在处理变量名称并不始终已知的 MAT 文件时,此方法很有用。
构造一个 MatFile
对象,该对象对应于示例文件 topography.mat
。使用 who
函数将文件中的变量名称存储在元胞数组 varlist
中。
exampleObject = matfile("topography.mat");
varlist = who(exampleObject)
varlist = 3x1 cell
{'topo' }
{'topomap1'}
{'topomap2'}
第二个和第三个变量 topomap1
和 topomap2
均为包含颜色图数据的三列矩阵。将这两个变量的第三列中的颜色图数据加载到结构体 S
的一个字段中。对于每个字段,指定一个由原始变量名称前附加 "colormap_"
构成的字段名称。然后,访问每个变量中作为 exampleObject
的属性的数据。由于 varName
为变量,因此将其括在圆括号中。
for index = 2:3 varName = varlist{index}; S.("colormap_"+varName) = exampleObject.(varName)(:,3); end
查看结构体的内容。结构体具有两个字段,即 colormap_topomap1
和 colormap_topomap2
,每个字段包含一个列向量。
S
S = struct with fields:
colormap_topomap1: [64x1 double]
colormap_topomap2: [128x1 double]
避免意外加载整个变量
如果您不知道 MAT 文件中一个大型变量的大小,并且想要一次仅加载该变量的一部分,请不要使用 end
关键字。使用 end
关键字会将相关变量的全部内容临时加载到内存中。对于非常大的变量,加载过程可能会花费较长时间,也可能会产生 Out
of
Memory
错误。在这种情况下,应对 MatFile
对象调用 size
方法。
例如,以下代码会将 B
的完整内容临时加载到内存中:
lastColB = exampleObject.B(:,end);
改用以下代码可提高其性能:
[nrows,ncols] = size(exampleObject,'B');
lastColB = exampleObject.B(:,ncols);
类似地,任何时候使用 matObj.varName
形式的语法引用变量,例如 exampleObject.B
,MATLAB® 都会临时将整个变量加载到内存中。因此,请确保使用以下语法对 MatFile
对象调用 size
方法:
[nrows,ncols] = size(exampleObject,'B');
而不是将 exampleObject.B
的完整内容传递到 size
函数,
[nrows,ncols] = size(exampleObject.B);
语法的差异是细微的,但却是重要的。
部分加载和保存功能要求 7.3 版本的 MAT 文件
如果使用的是与 7 版本或更低版本的 MAT 文件关联的 MatFile
对象,任何加载或保存操作都会临时将整个变量加载到内存中。
使用 matfile
函数创建 7.3 版本格式的文件。例如,下面的代码
newfile = matfile('newfile.mat');
创建支持部分加载和保存的 MAT 文件。
但是,默认情况下,save
函数创建 7 版本的 MAT 文件。通过使用 -v7.3
选项调用 save
函数,将现有的 MAT 文件转换为 7.3 版本,例如:
load('durer.mat'); save('mycopy_durer.mat','-v7.3');
要更改预设以将新文件保存为 7.3 版本格式,请访问主页选项卡上的环境部分,然后点击 预设。选择 MATLAB > 常规 > MAT 文件。MATLAB Online™ 中未提供此预设。