Как записать список/массив пользовательских типов в файл HDF5?

Мне нужно записать некоторые данные в файл HDF5 с помощью С#. Я не привязан к какой-либо конкретной библиотеке, но единственная доступная библиотека, которую я смог найти, это HDF5DotNet (http://hdf5.net/). У меня есть простой класс, содержащий некоторые данные (просто использование значения по умолчанию инициализирует его, чтобы легко его проверить, обычно данные считываются с датчика):

public class mData
{
    public double temp = 123.456789;
    public double humid = 223.456789;
    public int chamberId = 5;
}

Как записать массив или список в файл HDF5? HDF5 кажется слишком хорошим, чтобы это был особый случай, но я не смог найти подходящей документации. Это то, что я пробовал, следуя примеру:

List<mData> mdl = new List<mData>();
mdl.Add(new mData()); // create some dummy data
mdl.Add(new mData());
mdl.Add(new mData());
string filename = "test.h5";

const int DATA_ARRAY_LENGTH = 3;
const int RANK = 1; // <- unsure about this one

H5FileId fileId = H5F.create(filename, H5F.CreateMode.ACC_TRUNC);
H5GroupId groupId = H5G.create(fileId, "/myGroup");

long[] dims = new long[RANK]; // <- unsure, extrapolated from example
dims[0] = DATA_ARRAY_LENGTH;

H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);
H5DataTypeId typeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE); // <- NATIVE_DOUBLE is definitely wrong but I dont know which type to use in this case

int typeSize = H5T.getSize(typeId);
H5DataSetId dataSetId = H5D.create(fileId, "/myDataset", typeId, spaceId);

H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE), 
  new H5Array<double>(mdl)); // <- NATIVE_DOUBLE and H5Array<double> are definitely wrong but again unsure which type to use in both cases

H5G.close(groupId);
H5F.close(fileId);

Любая помощь или указания в других библиотеках приветствуются!


person SCBuergel    schedule 16.09.2015    source источник
comment
Я бы использовал составной тип данных. Вот пример   -  person Timothy Brown    schedule 16.09.2015
comment
Этот пример — С++, и кажется, что его действительно не так просто перенести на С#, поскольку он включает в себя много управления памятью и другую библиотеку. Неужели HDF5 настолько недоступен для C#?   -  person SCBuergel    schedule 16.09.2015


Ответы (1)


Использование H5T.H5Type.STD_REF_OBJ вместо H5T.H5Type.NATIVE_DOUBLE работает.

Этот тестовый код,

static void Main(string[] args)
{
        SampleH5Modified sh5 = new SampleH5Modified("TestFile01.h5", 5);
        sh5.Run();
}

будет генерировать этот вывод:

Creating H5 file TestFile01.h5...
H5 file TestFile01.h5 created successfully!
Reading H5 file TestFile01.h5...
chamberId=1 humid=100 temp=80
chamberId=2 humid=101 temp=81
chamberId=3 humid=102 temp=82
chamberId=4 humid=103 temp=83
chamberId=5 humid=104 temp=84
Processing complete!
public class SampleH5Modified
{
    private string filename;
    private int count;
    const string dataSetName = "/SampleDataSet";

    public SampleH5Modified(string filename, int count)
    {
        this.filename = filename;
        this.count = count;
    }

    public void Run()
    {
        List<mData> data1 = new List<mData>();

        for (int i = 0; i < count; i++)
            data1.Add(new mData(i + 80, i + 100, i + 1));

        WriteData(data1);

        mData[] data2 = ReadData();

        foreach (mData d in data2)
            Console.WriteLine("chamberId={0} humid={1} temp={2}", d.chamberId, d.humid, d.temp);

        Console.WriteLine("Processing complete!");
    }

    private void WriteData(List<mData> data)
    {
        Console.WriteLine("Creating H5 file {0}...", filename);

        const int RANK = 1;
        long[] dims = new long[RANK];
        dims[0] = count;

        H5FileId fileId = H5F.create(filename, H5F.CreateMode.ACC_TRUNC);

        H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);

        H5DataTypeId typeId = H5T.copy(H5T.H5Type.STD_REF_OBJ);

        int typeSize = H5T.getSize(typeId);

        H5DataSetId dataSetId = H5D.create(fileId, dataSetName, typeId, spaceId);

        H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.STD_REF_OBJ), new H5Array<mData>(data.ToArray()));

        H5D.close(dataSetId);
        H5F.close(fileId);

        Console.WriteLine("H5 file {0} created successfully!", filename);
    }

    private mData[] ReadData()
    {
        Console.WriteLine("Reading H5 file {0}...", filename);

        H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDONLY);

        H5DataSetId dataSetId = H5D.open(fileId, dataSetName);

        mData[] readDataBack = new mData[count];

        H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.STD_REF_OBJ), new H5Array<mData>(readDataBack));

        H5D.close(dataSetId);
        H5F.close(fileId);

        return readDataBack;
    }
}
person jsanalytics    schedule 16.10.2015
comment
Привет, jstreet, я запустил ваш пример, и когда я открываю файл в представлении HDF, я просто получаю таблицу из 5 строк и 1 столбца, содержащую очень большие числа. Я думаю, что это просто сохранение ссылки на данные в памяти, которая теряется, когда программа перестает работать. Есть ли способ сохранить фактические данные в файле? - person Matt Williams; 21.01.2016