在 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 = 3×1 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: [64×1 double]
colormap_topomap2: [128×1 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 版本格式的文件。例如,以下代码创建支持部分加载和保存的 MAT 文件。
newfile = matfile('newfile.mat');
但是,默认情况下,save 函数创建 7 版本的 MAT 文件。通过使用 -v7.3 选项调用 save 函数,将现有的 MAT 文件转换为 7.3 版本,例如:
load('durer.mat');
save('mycopy_durer.mat','-v7.3');要将您的设置更改为以版本 7.3 格式保存新文件,请转至主页选项卡,并在环境部分中点击 设置。选择 MATLAB > 常规 > MAT 和 FIG 文件,然后从可用选项中进行选择。