【问题标题】:Matlab Create MD5 Checksum for VariablesMatlab 为变量创建 MD5 校验和
【发布时间】:2017-06-21 22:58:41
【问题描述】:

为了调试,我希望比较几个对象,并为每个对象创建一些唯一的 ID,根据其内容和结构,ID 应该相等。是否有任何现有的功能可以做到这一点?

例如,如果一个对象是一个结构:

S:
 S.a1 = 1
 S.a2 = 2
 S.b1 = 3
   S.b11 = 4
   S.b12 = 5
 S.c1 = 6

我目前的选择是将其复制到磁盘并计算 MD5 64 位校验和,这不起作用,因为此哈希取决于文件的修改日期。

【问题讨论】:

    标签: matlab md5 checksum


    【解决方案1】:

    提到了一个解决方案hereDataHash函数就是那个解决方案:

    function H = DataHash(Data)
    Engine = java.security.MessageDigest.getInstance('MD5');
    H = CoreHash(Data, Engine);
    H = sprintf('%.2x', H);   % To hex string
    
    
    function H = CoreHash(Data, Engine)
    % Consider the type of empty arrays:
    S = [class(Data), sprintf('%d ', size(Data))];
    Engine.update(typecast(uint16(S(:)), 'uint8'));
    H = double(typecast(Engine.digest, 'uint8'));
    if isa(Data, 'struct')
       n = numel(Data);
       if n == 1  % Scalar struct:
          F = sort(fieldnames(Data));  % ignore order of fields
          for iField = 1:length(F)
             H = bitxor(H, CoreHash(Data.(F{iField}), Engine));
          end
       else  % Struct array:
          for iS = 1:n
             H = bitxor(H, CoreHash(Data(iS), Engine));
          end
       end
    elseif isempty(Data)
       % No further actions needed
    elseif isnumeric(Data)
       Engine.update(typecast(Data(:), 'uint8'));
       H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
    elseif ischar(Data)  % Silly TYPECAST cannot handle CHAR
       Engine.update(typecast(uint16(Data(:)), 'uint8'));
       H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
    elseif iscell(Data)
       for iS = 1:numel(Data)
          H = bitxor(H, CoreHash(Data{iS}, Engine));
       end
    elseif islogical(Data)
       Engine.update(typecast(uint8(Data(:)), 'uint8'));
       H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
    elseif isa(Data, 'function_handle')
       H = bitxor(H, CoreHash(functions(Data), Engine));
    else
       warning(['Type of variable not considered: ', class(Data)]);
    end
    

    另外,您还可以找到代码here的完整版本。

    【讨论】:

    • 这正是我想要的解决方案。我已经实现了。
    【解决方案2】:

    比@OmG 的答案更通用的解决方案,它依赖于一些未记录的功能:

    function str = hash(in)
    
    % Get a bytestream from the input. Note that this calls saveobj.
    inbs = getByteStreamFromArray(in);
    
    % Create hash using Java Security Message Digest.
    md = java.security.MessageDigest.getInstance('SHA1');
    md.update(inbs);
    
    % Convert to uint8.
    d = typecast(md.digest, 'uint8');
    
    % Convert to a hex string.
    str = dec2hex(d)';
    str = lower(str(:)');
    

    如果您对变量调用save -v7 命令,未记录的函数getByteStreamFromArray 返回将写入磁盘的字节流。它适用于大小小于 2GB 的任何变量,不仅包括 @OmG 的 CoreHash 涵盖的内置类型(数字、逻辑、结构、单元格等),还包括内置和用户也定义了类。

    注意getByteStreamFromArray 调用saveobj,所以它会忽略Transient 属性——这对于散列和保存几乎肯定是一件好事。

    PS 在任一解决方案中,SHA1 都可能优于 MD5。

    【讨论】:

      猜你喜欢
      • 2021-04-03
      • 2021-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-02
      • 1970-01-01
      相关资源
      最近更新 更多