Main Content

在 MAT 文件中保存和加载部分变量

您可以在 MAT 文件中直接保存和加载部分变量,而无需使用 matfile 函数将其加载到内存中。相对于 loadsave 函数,使用 matfile 函数的主要优点是对于太大而无法装入内存中的数据集,可以仅处理该数据集的一部分。当处理这些大型变量时,应一次将尽可能多的数据读取和写入到内存中。否则,重复的文件访问会严重降低代码的性能。

使用 matfile 函数保存和加载

此示例说明如何使用 matfile 函数在现有 MAT 文件中加载、修改和保存变量的一部分。

创建具有两个变量 AB 的 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'}

第二个和第三个变量 topomap1topomap2 均为包含颜色图数据的三列矩阵。将这两个变量的第三列中的颜色图数据加载到结构体 S 的一个字段中。对于每个字段,指定一个由原始变量名称前附加 "colormap_" 构成的字段名称。然后,访问每个变量中作为 exampleObject 的属性的数据。由于 varName 为变量,因此将其括在圆括号中。

for index = 2:3
    varName = varlist{index};
    S.("colormap_"+varName) = exampleObject.(varName)(:,3);
end

查看结构体的内容。结构体具有两个字段,即 colormap_topomap1colormap_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™ 中未提供此预设。

另请参阅

| |

相关主题