寻找能够读取HDF4文件格式的.NET库

时间:2009-11-30 12:19:22

标签: .net

有没有人知道一个简单的库来从.NET框架中的HDF files读取数据?

3 个答案:

答案 0 :(得分:2)

刚才我处理这个问题时,我找不到HDF4 for .NET的任何内容。 (我认为这是有道理的,因为HDF4不再受到支持,HDF4最早是在1995年左右创建的。)

我最终做的是滚动我自己的库来执行非常具体的命令来传达HDF文件。其中大部分都不值得分享,但以下内容可能有助于P / Invoke签名(并非所有签名都可能已经过测试等)。

public class HDF4
{
    #region DLL Imports
    private const string HDF4DLL = "hm421m.dll";

    #region file / dataset access

    [DllImport(HDF4DLL)]
    public static extern int SDcreate(int sd_id, string name, DataTypeDefinitions data_type, int rank, int[] dimsizes);

    [DllImport(HDF4DLL)]
    public static extern int SDstart(string filename, AccessCodes access_mode);

    [DllImport(HDF4DLL)]
    public static extern short SDendaccess(int sds_id);

    [DllImport(HDF4DLL)]
    public static extern short SDend(int sd_id);

    #endregion

    #region data access

    [DllImport(HDF4DLL)]
    public static extern int SDselect(int sd_id, int sds_index);

    [DllImport(HDF4DLL)]
    public static extern int SDreaddata(int sds_id, int[] start, int[] stride, int[] edge, IntPtr buffer);

    [DllImport(HDF4DLL)]
    public static extern int SDwritedata(int sds_id, int[] start, int[] stride, int[] edge, IntPtr buffer);

    [DllImport(HDF4DLL)]
    public static extern short SDgetdatastrs(int sds_id, StringBuilder label, StringBuilder unit, StringBuilder format, int length);

    [DllImport(HDF4DLL)]
    public static extern short SDsetdatastrs(int sds_id, string label, string unit, string format, string coordsys);

    #endregion

    #region dim

    [DllImport(HDF4DLL)]
    public static extern int SDgetdimid(int sds_id, int dim_index);

    [DllImport(HDF4DLL)]
    public static extern short SDdiminfo(int dim_id, StringBuilder name, out int size, out DataTypeDefinitions datay_type, out int num_attrs);

    [DllImport(HDF4DLL)]
    public static extern short SDgetdimstrs(int dim_id, StringBuilder label, StringBuilder unit, StringBuilder format, int length);

    [DllImport(HDF4DLL)]
    public static extern short SDgetdimscale(int dim_id, IntPtr data);

    [DllImport(HDF4DLL)]
    public static extern short SDsetdimname(int dim_id, string dim_name);

    [DllImport(HDF4DLL)]
    public static extern short SDsetdimscale(int dim_id, int count, DataTypeDefinitions data_type, IntPtr data);

    [DllImport(HDF4DLL)]
    public static extern short SDsetdimstrs(int dim_id, string label, string unit, string format);

    #endregion

    #region lookups / checks

    [DllImport(HDF4DLL)]
    public static extern int SDcheckempty(int sds_id, out bool emptySDS);

    [DllImport(HDF4DLL)]
    public static extern int SDnametoindex(int sd_id, string sds_name);

    [DllImport(HDF4DLL)]
    public static extern int SDfileinfo(int sd_id, out int num_datasets, out int num_global_attrs);

    [DllImport(HDF4DLL)]
    public static extern short SDgetinfo(int sds_id, StringBuilder sds_name, out int rank, [In, Out] int[] dimsizes, out DataTypeDefinitions data_type,
        out int num_attrs);

    [DllImport(HDF4DLL)]
    public static extern bool SDiscoordvar(int sds_id);


    #endregion

    #region attr

    [DllImport(HDF4DLL)]
    public static extern int SDfindattr(int obj_id, string attr_name);

    [DllImport(HDF4DLL)]
    public static extern short SDattrinfo(int obj_id, int attr_index, StringBuilder attr_name, out DataTypeDefinitions data_type, out int count);

    [DllImport(HDF4DLL)]
    public static extern short SDreadattr(int obj_id, int attr_index, StringBuilder attr_buff);

    [DllImport(HDF4DLL)]
    public static extern short SDsetattr(int obj_id, string attr_name, DataTypeDefinitions data_type, int count, StringBuilder values);

    #endregion

    #endregion

    #region Enums / Consts

    public const uint DFNT_NATIVE = 4096;
    public const int MAX_VAR_DIMS = 32;

    [Flags]
    public enum DataTypeDefinitions : uint
    {
        DFNT_CHAR8      = 4,
        DFNT_CHAR       = 4,
        DFNT_UCHAR8     = 3,
        DFNT_UCHAR      = 3,
        DFNT_INT8       = 20,
        DFNT_UINT8      = 21,
        DFNT_INT16      = 22,
        DFNT_UINT16     = 23,
        DFNT_INT32      = 24,
        DFNT_UINT32     = 25,
        DFNT_FLOAT32    = 5,
        DFNT_FLOAT64    = 6,
        DFNT_NINT8      = DFNT_NATIVE | DFNT_INT8,
        DFNT_NUINT8     = DFNT_NATIVE | DFNT_UINT8,
        DFNT_NINT16     = DFNT_NATIVE | DFNT_INT16,
        DFNT_NUINT16    = DFNT_NATIVE | DFNT_UINT16,
        DFNT_NINT32     = DFNT_NATIVE | DFNT_INT32,
        DFNT_NUINT32    = DFNT_NATIVE | DFNT_UINT32,
        DFNT_NFLOAT32   = DFNT_NATIVE | DFNT_FLOAT32,
        DFNT_NFLOAT64   = DFNT_NATIVE | DFNT_FLOAT64
    }

    public enum AccessCodes
    {
        DFACC_READ      = 1,
        DFACC_WRITE     = 2,
        DFACC_CREATE    = 4,
        DFACC_ALL       = 7,
        DFACC_RDONLY    = 1,
        DFACC_RDWR      = 3
    }

    #endregion

    #region Helper Functions

    public static double[] SDgetdimscaledouble(int dim_id, int size)
    {
        double d = 0;
        IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(d) * size);
        SDgetdimscale(dim_id, p);
        double[] dest = new double[size];
        Marshal.Copy(p, dest, 0, size);
        Marshal.FreeHGlobal(p);
        return dest;
    }

    public static void SDsetdimscaledouble(int dim_id, double[] d)
    {
        IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(d[0])*d.Length);
        Marshal.Copy(d, 0, p, d.Length);
        int res = SDsetdimscale(dim_id, d.Length, DataTypeDefinitions.DFNT_FLOAT64, p);
        Marshal.FreeHGlobal(p);
    }

    public static double SDreaddouble(int sds_id, int[] start, int[] edge)
    {
        double d = 0;
        IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(d));
        SDreaddata(sds_id, start, null, edge, p);
        double[] dest = new double[1];
        Marshal.Copy(p, dest, 0, 1);
        d = dest[0];
        Marshal.FreeHGlobal(p);
        return d;
    }

    public static void SDwritedouble(int sds_id, int[] start, int[] edge, double d)
    {
        IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(d));
        double[] a = new double[1];
        a[0] = d;
        Marshal.Copy(a, 0, p, 1);
        int res = SDwritedata(sds_id, start, null, edge, p);
        Marshal.FreeHGlobal(p);
    }

    #endregion
}

因此,您可以为文件,数据集,维度,属性等创建对象。对于文件,这是一个片段:

public class HDFFile : IDisposable
{
    // snip

    public static HDFFile New(string fullfilename)
    {
        HDFFile hdf = new HDFFile(fullfilename);

        hdf._sdId = HDF4.SDstart(fullfilename, HDF4.AccessCodes.DFACC_CREATE);

        return hdf;
    }

    public static HDFFile Open(string fullfilename)
    {
        HDFFile hdf = new HDFFile(fullfilename);

        hdf._sdId = HDF4.SDstart(fullfilename, HDF4.AccessCodes.DFACC_RDWR);

        if (hdf._sdId == -1)
            throw new Exception("Could not open " + fullfilename);

        hdf.Load();

        return hdf;
    }

    private void Load()
    {
        int num_ds = 0;
        int num_global = 0;
        HDF4.SDfileinfo(_sdId, out num_ds, out num_global);

        for (int i = 0; i < num_ds; i++)
        {
            HDFDataSet hds = HDFDataSet.Load(_sdId, i);
            if (!string.IsNullOrEmpty(hds.Name))
                _dataSets.Add(hds);
        }

        _attributes = HDFAttribute.Load(_sdId, num_global);
    }

    // snip
}

答案 1 :(得分:1)

您发布的网站上有一个不受支持的解决方案

ftp://ftp.hdfgroup.uiuc.edu/pub/outgoing/hdf5/HDF5dotNetEnv/

答案 2 :(得分:0)

更好的方法是从HDF对象本身抽象元数据; HDF小组正在开发一种映射工具,可以转储有关如何从HDF文件(即SDS,RIS,VData等)获取原始数据类型的信息,这样您就可以编写自己的读取器而无需使用HDF / Net CDF库。

http://www.hdfgroup.org/projects/h4map/