查找 .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)自行编写代码。 我已经尝试过h5diffdllh5lsdll,但是对于非平凡的文件,输出太多而无法在 cmd 中显示。您能否提示我如何在文本文件中获取结果,以便我可以稍微清理一下? 看起来你在 Windows 上,抱歉我不知道如何重定向输出。对于类似 unix 的系统,它将是 YOUR_COMMAND &gt; 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.matf2.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

鉴于您想比较myStruct1myStruct2,您只需调用:

[fs1, fs2, er] = comp_struct(myStruct1,myStruct2)

我对@9​​87654329@ 中差异列表的可读性感到非常惊讶,这是问题中使用的示例的输出:

呃 =

'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 文件之间的所有差异的主要内容,如果未能解决你的问题,请参考以下文章

awk 查找两个文件中第二个字段之间的差异

查找两个文本文件之间的差异,每行一项[重复]

使用python查找两个csv文件列之间的差异

Python Pandas - 查找两个数据帧之间的差异

在python中查找字符串时间对象之间的差异

在 MS Access 或 SQL Server 中查找 2 个表之间的差异