HDF5 : 可変長文字列の書き込み2013年02月14日 21:35

可変長な文字列の書き込みと読み込みについて
文字の書き込みと読み込みについては、一度固定長の文字列について言及したが、今回は可変長の文字列について

書き込みには"H5DataSetId"クラス("H5DataSetId"クラスを作成するには”H5DataSpaceId”クラスと"H5DataTypeId"クラスが必要)と"H5DataTypeId"クラスが必要になる点はかわらない。
違う点について、
 固定長時は文字列を文字列データとして扱うために、byte配列に変換、変換データを用いて"H5DataType"クラスのサイズ設定と”write<>”メソッドをbyte型にて実行した。
 可変長時はC++などで使用するポインタを使用(といってもポインタを意識するような使い方はしなくてもよい)して、"H5DataSetId"クラスの作成や"write<>"メソッドの実行を行う。

"H5DataSpaceId"クラスの作成については、今までと変わらないので、固定長のものを参考に、ここでは割愛。

"H5DataTypeId"クラスを作成する場合は、"H5T"クラスの"create"メソッドを使用するが、引数の"size"(int型)に-1を指定する。これは、可変長の文字列を使用するときには必ず行う。
H5DataTypeId typeID = H5T.create(H5T.CreateClass.STRING,-1);
"H5DataSetId"クラスは上記の"H5DataSpaceId"クラスと"H5DataTypeId"で作成。作成方法は今までと同じなので割愛。

次に文字列のデータの作成。文字列データへの変換には"UTF8Encoding"クラスなどのEncoding系クラスを使用せず、System.Runtime.InteropServices空間にある"Marshal"クラスにある"StringToHGlobalAnsi"メソッドを使用する。引数は"string"クラス、戻り値は"IntPtr"構造体。要するに、アンマネージ領域に文字列データを用意しておき、ポインタを使用して書き込む。
IntPtr stringPtr = Marshal.StringToHGlobalAnsi( stringValue );
これで、"H5D"クラスの"write<>"メソッドを実行する。ジェネリックの指定はもちろん"IntPtr"構造体を使用する。
H5Array<IntPtr> dataArray = new H5Array<IntPtr>( new []{stringPtr} );
H5D
.write<IntPtr>( datasetID, ftypeID, dataArray ) );
使用後は、"close"メソッドができるものは行う。"IntPtr"構造体については"Marshal"クラスにある"FreeHGlobal"メソッドを使用してメモリを開放する。引数は"IntPtr"構造体。
Marshal.FreeHGlobal( stringPtr );
以下、サンプル。
H5FileId fileID = H5F.create("C:\\Test.hdf5" , H5F.CreateMode.ACC_TRUNC );
H5DataTypeId typeID = H5T.create(H5T.CreateClass.STRING,-1); H5DataSetId datasetID = H5D.create( fileID, "VariableStr", typeID, spaceID ); string stringValue = "This is TestString.";
IntPtr stringPtr = Marshal.StringToHGlobalAnsi( stringValue );
H5Array<IntPtr> dataArray = new H5Array<IntPtr>( new []{stringPtr} );
H5D
.write<IntPtr>( datasetID, typeID, dataArray ) );
H5D.close( datasetID );
H5T.close( typeID ); 
H5S.close( spaceID );
H5F.close( fileID );
Marshal.FreeHGlobal( stringPtr );