C# 如何使用HDF5DOTNET创建复合数据类型?
我在将包含数组的结构写入HDF5数据集中时遇到问题。首先,窗口窗体不以行开头:C# 如何使用HDF5DOTNET创建复合数据类型?,c#,hdf5,hdf5dotnet,C#,Hdf5,Hdf5dotnet,我在将包含数组的结构写入HDF5数据集中时遇到问题。首先,窗口窗体不以行开头: H5T.insert(typeStruct,“string”,0,H5T.create_数组(新的H5DataTypeId(H5T.H5Type.C_S1),dims2)) 窗口窗体至少在没有行的情况下启动,因此我认为定义复合数据类型有问题。我已经查阅了手册和许多示例,但仍然无法解决这些问题。我能举一个使用复合数据类型在C#中编写具有多个数组的结构的例子吗 使用HDF5DotNet; 利用制度全球化; 使用Syste
H5T.insert(typeStruct,“string”,0,H5T.create_数组(新的H5DataTypeId(H5T.H5Type.C_S1),dims2))代码>
窗口窗体至少在没有行的情况下启动,因此我认为定义复合数据类型有问题。我已经查阅了手册和许多示例,但仍然无法解决这些问题。我能举一个使用复合数据类型在C#中编写具有多个数组的结构的例子吗
使用HDF5DotNet;
利用制度全球化;
使用System.IO;
使用System.Runtime.InteropServices;
运用系统反思;
命名空间Windows窗体应用程序1
{
公共不安全部分类Form1:Form
{
公共不安全结构
{
公共字符串[]arr_currentLong;
公共结构\u TR(字节大小\u当前时间)
{
arr_currentLong=新字符串[size_currentTime];
}
}
公共表格1()
{
初始化组件();
长数组_SIZE=255;
struct_TR structmake=new struct_TR(255);
对于(int i=0;i<255;i++)
{
structmake.arr_currentLong[i]=i.ToString();
}
字符串currentPath=Path.GetDirectoryName(Application.ExecutablePath);
目录.SetCurrentDirectory(currentPath);
H5FileId fileId=H5F.create(@“weights.h5”,H5F.CreateMode.ACC_TRUNC);
长[]dims1={1};
long[]dims2={1,数组_SIZE};
H5DataSpaceId myDataSpace=H5S.create_simple(1,dims1);
H5DataTypeId string_type=H5T.copy(H5T.H5Type.C_S1);
H5DataTypeId数组_tid1=H5T.创建数组(字符串类型,dims2);
H5DataTypeId typeStruct=H5T.create(H5T.CreateClass.component,Marshal.SizeOf(typeof(struct_TR));
H5T.insert(typeStruct,“string”,0,H5T.create_数组(新的H5DataTypeId(H5T.H5Type.C_S1),dims2));
H5DataSetId myDataSet=H5D.create(fileId,“/dset”,typeStruct,myDataSpace);
H5D.writeScalar(myDataSet、typeStruct、ref StructMake);
}
}
}
我知道如何使用数组保存结构的唯一方法是创建一个常量数组
例如,这是一个数组长度为4的结构
[StructLayout(LayoutKind.Sequential)]
public struct Responses
{
public Int64 MCID;
public int PanelIdx;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public short[] ResponseValues;
}
此处创建了包含数组的4个结构的数组:
responseList = new Responses[4] {
new Responses() { MCID=1,PanelIdx=5,ResponseValues=new short[4]{ 1,2,3,4} },
new Responses() { MCID=2,PanelIdx=6,ResponseValues=new short[4]{ 5,6,7,8}},
new Responses() { MCID=3,PanelIdx=7,ResponseValues=new short[4]{ 1,2,3,4}},
new Responses() { MCID=4,PanelIdx=8,ResponseValues=new short[4]{ 5,6,7,8}}
};
以下代码行将结构数组写入HDF5文件:
string filename = "testArrayCompounds.H5";
var fileId =H5F.create(filename, H5F.ACC_TRUNC);
var status = WriteCompounds(fileId, "/test", responseList);
H5F.close(fileId);
WriteCompounds方法如下所示:
public static int WriteCompounds<T>(hid_t groupId, string name, IEnumerable<T> list) //where T : struct
{
Type type = typeof(T);
var size = Marshal.SizeOf(type);
var cnt = list.Count();
var typeId = CreateType(type);
var log10 = (int)Math.Log10(cnt);
ulong pow = (ulong)Math.Pow(10, log10);
ulong c_s = Math.Min(1000, pow);
ulong[] chunk_size = new ulong[] { c_s };
ulong[] dims = new ulong[] { (ulong)cnt };
long dcpl = 0;
if (!list.Any() || log10 == 0) { }
else
{
dcpl = CreateProperty(chunk_size);
}
// Create dataspace. Setting maximum size to NULL sets the maximum
// size to be the current size.
var spaceId = H5S.create_simple(dims.Length, dims, null);
// Create the dataset and write the compound data to it.
var datasetId = H5D.create(groupId, name, typeId, spaceId, H5P.DEFAULT, dcpl);
IntPtr p = Marshal.AllocHGlobal(size * (int)dims[0]);
var ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);
foreach (var strct in list)
writer.Write(getBytes(strct));
var bytes = ms.ToArray();
GCHandle hnd = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var statusId = H5D.write(datasetId, typeId, spaceId, H5S.ALL,
H5P.DEFAULT, hnd.AddrOfPinnedObject());
hnd.Free();
/*
* Close and release resources.
*/
H5D.close(datasetId);
H5S.close(spaceId);
H5T.close(typeId);
H5P.close(dcpl);
Marshal.FreeHGlobal(p);
return statusId;
}
我还有一个ReadComponents来读取hdf5文件。CreateType方法中使用的Hdf5.GetCompoundInfo方法也很长。所以我在这里不展示这些方法
因此,仅仅为了编写一些结构,就需要编写大量的代码。
我创建了一个名为的库,它允许您更轻松地读写类和结构。在那里,您还可以找到ReadComponents和GetCompoundInfo方法
在的单元测试中,您还可以找到如何使用数组编写类的示例感谢您的详细解释和示例代码!我从你的回答中学到了很多!
public static int WriteCompounds<T>(hid_t groupId, string name, IEnumerable<T> list) //where T : struct
{
Type type = typeof(T);
var size = Marshal.SizeOf(type);
var cnt = list.Count();
var typeId = CreateType(type);
var log10 = (int)Math.Log10(cnt);
ulong pow = (ulong)Math.Pow(10, log10);
ulong c_s = Math.Min(1000, pow);
ulong[] chunk_size = new ulong[] { c_s };
ulong[] dims = new ulong[] { (ulong)cnt };
long dcpl = 0;
if (!list.Any() || log10 == 0) { }
else
{
dcpl = CreateProperty(chunk_size);
}
// Create dataspace. Setting maximum size to NULL sets the maximum
// size to be the current size.
var spaceId = H5S.create_simple(dims.Length, dims, null);
// Create the dataset and write the compound data to it.
var datasetId = H5D.create(groupId, name, typeId, spaceId, H5P.DEFAULT, dcpl);
IntPtr p = Marshal.AllocHGlobal(size * (int)dims[0]);
var ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);
foreach (var strct in list)
writer.Write(getBytes(strct));
var bytes = ms.ToArray();
GCHandle hnd = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var statusId = H5D.write(datasetId, typeId, spaceId, H5S.ALL,
H5P.DEFAULT, hnd.AddrOfPinnedObject());
hnd.Free();
/*
* Close and release resources.
*/
H5D.close(datasetId);
H5S.close(spaceId);
H5T.close(typeId);
H5P.close(dcpl);
Marshal.FreeHGlobal(p);
return statusId;
}
private static long CreateType(Type t)
{
var size = Marshal.SizeOf(t);
var float_size = Marshal.SizeOf(typeof(float));
var int_size = Marshal.SizeOf(typeof(int));
var typeId = H5T.create(H5T.class_t.COMPOUND, new IntPtr(size));
var compoundInfo = Hdf5.GetCompoundInfo(t);
foreach (var cmp in compoundInfo)
{
H5T.insert(typeId, cmp.name, Marshal.OffsetOf(t, cmp.name), cmp.datatype);
}
return typeId;
}
private static long CreateProperty(ulong[] chunk_size)
{
var dcpl = H5P.create(H5P.DATASET_CREATE);
H5P.set_layout(dcpl, H5D.layout_t.CHUNKED);
H5P.set_chunk(dcpl, chunk_size.Length, chunk_size);
H5P.set_deflate(dcpl, 6);
return dcpl;
}