查找 .mat 文件之间的所有差异
Posted
技术标签:
【中文标题】查找 .mat 文件之间的所有差异【英文标题】:Find all differences between .mat files 【发布时间】:2013-10-08 16:23:45 【问题描述】:我正在寻找一种方法来列出两个 .mat 文件之间的差异,这对许多人来说可能很有用。
虽然我到处搜索我能想到的,但我没有找到任何符合我要求的东西:
-
选择 2 个 mat 文件
找出差异
妥善保存
我最接近的是visdiff
。只要我留在matlab中,它就可以让我浏览差异,但是当我保存结果时,它只显示***。
这是我的文件通常看起来的简化示例:
a = 6;
b.c.d = 7;
b.c.e = 'x';
save f1
f = a;
clear a
b.c.e = 'y';
save f2
visdiff('f1.mat','f2.mat')
如果我点击这里b
,我可以找到不同之处。但是,如果我运行它并使用“文件>保存”,我将无法单击 b
。因此,我仍然不知道发生了什么变化。
注意:我没有 Simulink
因此我的问题是:
如何向没有 Matlab 的人展示 2 个 mat 文件之间的所有差异
以下是我个人认为最适合不同情况的答案:
Answer for users with Simulink General answer Answer displaying all value differences【问题讨论】:
我假设您提到的“文件->另存为”与“另存为 html”功能有关 (mathworks.co.uk/help/matlab/matlab_env/…)。这是否不允许深入研究结构等? @am304 试过了,但结果只是一个html'图片',不允许你点击和向下钻取。 好的,可能值得将其报告为未来版本的增强请求,即使它现在对您没有帮助 您可以使用Simulink.saveVars
而不是save
。看我的回答
已更新问题,因为我没有可用的 Simulink。
【参考方案1】:
找出没有 MATLAB 的 mat 文件之间的所有差异?
您可以找到基于.mat files 的HDF5 与HDF5 Tools 之间的区别。
示例
让我缩短您的 MATLAB 示例并假设您使用
创建了两个 mat 文件clear ; a = 6 ; b.c = 'hello' ; save -v7.3 f1
clear ; a = 7 ; b.e = 'world' ; save -v7.3 f2
在 MATLAB 之外使用
h5ls -v -r f1.mat
获取有关包含 f1.mat 的数据类型的列表:
Opened "f1.mat" with sec2 driver.
/ Group
Location: 1:96
Links: 1
/a Dataset 1/1, 1/1
Attribute: MATLAB_class scalar
Type: 6-byte null-terminated ASCII string
Data: "double"
Location: 1:2576
Links: 1
Storage: 8 logical bytes, 8 allocated bytes, 100.00% utilization
Type: native double
/b Group
Attribute: MATLAB_class scalar
Type: 6-byte null-terminated ASCII string
Data: "struct"
Location: 1:800
Links: 1
/b/c Dataset 5/5, 1/1
Attribute: H5PATH scalar
Type: 2-byte null-terminated ASCII string
Data: "/b"
Attribute: MATLAB_class scalar
Type: 4-byte null-terminated ASCII string
Data: "char"
Attribute: MATLAB_int_decode scalar
Type: native int
Data: 2
Location: 1:1832
Links: 1
Storage: 10 logical bytes, 10 allocated bytes, 100.00% utilization
Type: native unsigned short
使用
h5ls -d -r f1.mat
返回存储数据的值:
/ Group
/a Dataset 1, 1
Data:
(0,0) 6
/b Group
/b/c Dataset 5, 1
Data:
(0,0) 104, 101, 108, 108, 111
数据104, 101, 108, 108, 111
代表单词hello
,可以用
h5ls -d -r f1.mat | tail -1 | awk 'FS=",";printf("%c%c%c%c%c \n",$2,$3,$4,$5,$6)'
您可以获得 f2.mat 的相同列表,并将两个输出与您选择的工具进行比较。
Comparison 也可以直接与HDF5 Tools 一起使用。要比较两个文件中的两个数字a
,请使用
h5diff -r f1.mat f2.mat /a
这将向您显示值及其差异
dataset: </a> and </a>
size: [1x1] [1x1]
position a a difference
------------------------------------------------------------
[ 0 0 ] 6 7 1
1 differences found
attribute: <MATLAB_class of </a>> and <MATLAB_class of </a>>
0 differences found
备注
HDF5 Tools 中有更多命令和选项,可能有助于解决您的实际问题。
可从The HDF Group 获得适用于 Linux 和 Windows 的二进制发行版。对于 OS X,您可以通过 MacPorts 安装它们。如果需要,还有一个 GUI:HDFView。
【讨论】:
很好奇它是否适用于非平凡的mat文件,到目前为止我很乐观。 如果您无法使用 HDF5 工具,您可以尝试通过Mathworks 和/或HDF group 联系支持团队。或者尝试使用任何读取 HDF5 文件的语言(例如带有h5py 的python)自行编写代码。 我已经尝试过h5diffdll
和h5lsdll
,但是对于非平凡的文件,输出太多而无法在 cmd 中显示。您能否提示我如何在文本文件中获取结果,以便我可以稍微清理一下?
看起来你在 Windows 上,抱歉我不知道如何重定向输出。对于类似 unix 的系统,它将是 YOUR_COMMAND > YOUR_FILE
。
幸运的是,它也适用于 Windows,而且它还将处理时间从半分钟缩短到几分之一秒!【参考方案2】:
如果您有 simulink,您可以使用 Simulink.saveVars
生成一个 m 文件,该文件在执行时会在工作空间中创建相同的变量:
a = 6;
b.c.d = 7;
b.c.e = 'x';
Simulink.saveVars('f1');
f = a;
clear a
b.c.e = 'y';
Simulink.saveVars('f2');
visdiff('f1.m','f2.m')
如本截图所示
请注意,默认情况下,它将数组中的元素数限制为 1000,您可以将其增加到 10000。大于该限制的数组将保存在单独的 mat 文件中。
更新:从 R2014a 开始,一个类似于 Simulink.saveVars
的新函数已添加到 MATLAB。见matlab.io.saveVariablesToScript
【讨论】:
我只是在阅读此答案后提到我缺乏 Simulink。所以不要仅仅因为这个原因而投反对票。【参考方案3】:这只是部分答案,但也许有帮助。
您可以使用gencode,这是一个从变量生成 Matlab 代码的 Matlab 函数,以便运行代码重现变量。您对每个 mat 文件中的所有变量执行此操作(需要一些编程,但应该可行)并将结果放入不同的 .m 文件中。
然后您使用标准文本比较工具(甚至可能是visdiff
)来比较 .m 文件。
【讨论】:
我已尝试实施您的解决方案,但仍遇到一些困难。看我的回答。【参考方案4】:有几个很好的工具可以比较 XML 文件,我会这样处理:
-
下载struct2xml.m
加载两个 matfile
用 struct2xml 导出每个
比较,使用 XMLSpy 或类似方法
【讨论】:
我还没有测试它,但到目前为止这看起来可能是最方便的。 File Exchange 上有许多函数可以将 MATLAB 变量转换为文本表示形式(XML、JSON、..)。可以使用任何常规 diff 工具来比较这些输出 虽然这个提交对我的结构(甚至标量)不起作用,但它确实为我指明了正确的方向。在阅读了这个答案并结合了@Amro 的建议后,我意识到将我的数据保存为纯文本(从而失去结构性质)会使任何比较都不切实际。我会尽快发布我找到的解决方案。【参考方案5】:简单的通用答案,不显示价值差异
由于我从@BHF、@Daniel R 和@Dennis Jaheruddin 的回答中获得的洞察力,我设法找到了一个简单的可扩展解决方案:
[fs1, fs2, er] = comp_struct(load('f1.mat'),load('f2.mat'))
请注意,它适用于包含任意数量变量的 .mat。
这使用Compare Structures - File Exchange submission。
【讨论】:
现在无法测试,但它真的有效吗?保存文件中可以包含什么,每个结构只有 1 个或任意变量?确保可以单独阅读此答案(例如,无需人们在我现有的答案中寻找准备工作)。myStruct1=load('f1.mat');
确实创建了与您的内容相同的变量 myStruct1 ,仅此而已。这是等号的效果,也是在comp_struct
的参数中使用load的结果的效果。
最好的办法是编辑您的答案,但一位审阅者在 french.stackexchange.com/review/suggested-edits/8954 上教我更喜欢制作一个独立的答案。
它适用于包含任意数量变量的.mat。【参考方案6】:
小文件的答案,显示所有值差异
根据@A 的建议。 Donda 我尝试使用gencode
为所有内容创建一个变量。
虽然它适用于我的玩具示例,但速度很慢,并告诉我超出了真实 .mat 文件允许的变量数量。
无论如何,对于那些正在寻找适用于小文件的东西的人,我会发布这个选项:
wList=who;
for iLoop = 1:numel(wList)
eval(['generated_' wListiLoop '= gencode(' wListiLoop ');'])
for jLoop = 1:numel(eval(['generated_' wListiLoop]))
eval(['generated_' wListiLoop '_' num2str(jLoop) '= generated_' wListiLoop '(' num2str(jLoop) ');' ])
end
end
虽然它可能有效,但我觉得这不是最好的方法。
【讨论】:
是的,我想这种方式只有在生成的 m 文件具有合理大小时才有意义。我唯一能想到的就是修改 gencode,这样如果数据结构中涉及到大型数据矩阵,就不要生成代码来重新创建它们,而是对它们的内容进行一种总结,例如使用checksum。【参考方案7】:一般答案,不显示价值差异
由于我从@BHF 和@Daniel R 的答案中获得的洞察力,我设法找到了一个可合理扩展的解决方案。
第 1 步:将每个文件中的所有变量保存为单个结构
这使用Save workspace to struct - File Exchange submission。
假设您要比较 f1.mat
和 f2.mat
,请执行以下步骤:
clear
load f1
myStruct1 = ws2struct;
save myStruct1 myStruct1
clear
load f2
myStruct2 = ws2struct;
save myStruct2 myStruct2
clear
load myStruct1
load myStruct2
第 2 步:比较结构
这使用Compare Structures - File Exchange submission
鉴于您想比较myStruct1
和myStruct2
,您只需调用:
[fs1, fs2, er] = comp_struct(myStruct1,myStruct2)
我对@987654329@ 中差异列表的可读性感到非常惊讶,这是问题中使用的示例的输出:
呃 =
's2 is missing field a'
's1(1).b(1).c(1).e and s2(1).b(1).c(1).e do not match'
请注意,它不会显示值,从技术角度来看,如果需要显示值差异,更改 m 文件可能并不难。但是,特别是如果有一些大矩阵,我认为这可能会导致输出有问题。
【讨论】:
接受的答案简化了这一点。我将把这个答案留在这里,因为我不确定接受的答案是否对旧版本的 Matlab 有效。以上是关于查找 .mat 文件之间的所有差异的主要内容,如果未能解决你的问题,请参考以下文章