1

他のアプリケーションがデータファイルの読み取りと書き込みを行えるように、オブジェクトをXMLとして保存したいと思います。これは、Matlabのバイナリマットファイルでは非常に難しいことです。

私が遭遇している根本的な問題は、Matlabのリフレクション(.NETで同様のことを行うために使用した)に相当するものが、プライベートプロパティに関してあまり機能しないことです。Matlabのstruct(object)関数は、オブジェクトからXMLを作成するという点で、ハックを提供します。

x = myInstance.myPrivateProperty;

...できます

props = struct(myInstance);
x = props.myPrivateProperty;

したがって、以下のコードを使用して、任意のオブジェクトから純粋な(オブジェクトを含まない)構造体を作成できます。その後、純粋な構造体を使用してXMLファイルを作成するのは簡単です。

しかし、プロセスを逆にする方法はありますか?つまり、以下のコードによって保存されたデータを使用してオブジェクトインスタンスを作成するには(そのデータには、クラスインスタンスのすべての非依存、非定数、非一時プロパティのリスト、およびクラスの名前が含まれます)?私は、すべてのオブジェクトがXmlSerializableというクラスから継承することを考えていました。このクラスは、コンストラクターの単一の引数として構造体を受け入れ、構造体に含まれるすべての値を対応する名前のプロパティに割り当てます。ただし、MyClassがXmlSerializableを継承する場合、XmlSerializableのコードでMyClassのプライベートプロパティを設定することは許可されていないため、これは機能しません(プライベートプロパティを操作するための一般化された関数を作成するにはどうすればよいですか?)。これは.NETでは問題ありません(参照リフレクションで私有財産を設定することはできますか?)、しかし私はMatlabでそれを理解するのに苦労しています。

このコードは、渡されたオブジェクトのすべての状態情報を含み、オブジェクトインスタンスを含まない構造体を作成します。結果の構造体は、XMLに簡単に書き込むことができます。

function s = toPureStruct(thing)
    if isstruct(thing)
        s = collapseObjects(thing);
        s.classname = 'struct';
    elseif isobject(thing)
        s.classname = class(thing);
        warning off MATLAB:structOnObject;
        allprops = struct(thing);
        warning on MATLAB:structOnObject
        mc = metaclass(thing);
        for i=1:length(mc.PropertyList)
            p = mc.PropertyList(i);
            if strcmp(p.Name, 'classname')
                error('toStruct:PropertyNameCollision', 'Objects used in toStruct may not have a property named ''classname''');
            end
            if ~(p.Dependent || p.Constant || p.Transient)
                if isobject(allprops.(p.Name))
                    s.(p.Name) = toPureStruct(allprops.(p.Name));
                elseif isstruct(allprops.(p.Name))
                    s.(p.Name) = collapseObjects(allprops.(p.Name));
                else
                    s.(p.Name) = allprops.(p.Name);
                end
            end
        end
    else
        error(['Conversion to pure struct from ' class(thing) ' is not possible.']);
    end
end

function s = collapseObjects(s)
    fnames = fields(s);
    for i=1:length(fnames)
        f = s.(fnames{i});
        if isobject(f)
            s.(fnames{i}) = toPureStruct(f);
        elseif isstruct(f)
            s.(fnames{i}) = collapseObjects(f);
        end
    end
end

編集:保存されたファイルを読みたい他の「アプリケーション」の1つは、バージョン管理システム(Matlabオブジェクトによって定義された構成のパラメーターの変更を追跡するため)です。したがって、実行可能なソリューションは、人間が理解できるテキストを生成できる必要があります。上記のtoPureStructメソッドは、構造体がXMLに変換されるときにこれを行います。

4

2 に答える 2

1

保存したオブジェクトに新しいv7.3MATファイル形式を使用することで、この問題を回避できる場合があります。古いMATファイル形式とは異なり、v7.3はHDF5のバリアントであり、HDF5のサポートと他の言語のライブラリがあります。これははるかに少ない作業である可能性があり、HDF5は単純なXMLよりも効率的な数値配列の表現を備えているため、おそらくパフォーマンスも向上します。

これはデフォルトの形式ではありません。-v7.3機能への切り替えを使用して有効にすることができsaveます。

于 2012-10-11T06:30:00.457 に答える
0

私の知る限り、Matlab2011bではやりたいことは不可能です。@Andrew Jankeの回答によると、他のプログラムで読み取ったり変更したりできるバイナリHDF5ファイルに対してMatlabのloadコマンドを使用して、同様のことを行うことができる場合があります。ただし、最も単純なクラスでさえMatlabのHDF5表現は非常に不透明であるため、これにより非常に複雑になります。たとえば、2つの標準プロパティ(prop1とprop2)を使用してMatlabでSimpleClass classdefを作成すると、-v7.3スイッチで生成されたHDF5バイナリは7k、拡張XMLは21k、テキスト「prop1」と「 prop2"はどこにも表示されません。そのSimpleClassから本当に作成したいのはこれです:

<root>
  <classname>SimpleClass</classname>
  <prop1>123</prop1>
  <prop2>456</prop2>
</root>

たとえば.NETやJavaでは可能ですが、Matlabではクラスプロパティから上記のテキストを一般化された方法で作成することはできないと思います。

于 2012-12-19T20:10:46.933 に答える