首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C# .NET中读取HDF5可变长度字符串属性

如何在C# .NET中读取HDF5可变长度字符串属性
EN

Stack Overflow用户
提问于 2018-08-23 13:24:42
回答 2查看 1.2K关注 0票数 1

使用C#中的HDF.PInvoke库,如何读取可变长度字符串H5T_VARIABLE属性?

HDF5文件如下所示:

代码语言:javascript
复制
GROUP "/" {
   ATTRIBUTE "foo" {
      DATATYPE  H5T_STRING {
         STRSIZE H5T_VARIABLE;
         STRPAD H5T_STR_NULLTERM;
         CSET H5T_CSET_ASCII;
         CTYPE H5T_C_S1;
      }
      DATASPACE  SCALAR
      DATA {
      (0): "bar"
      }
   }
}

尝试像这样读取属性foo

代码语言:javascript
复制
long fileId = H5F.open("my-file.h5", H5F.ACC_RDWR);
long attrId = H5A.open(fileId, "foo");
long typeId = H5A.get_type(attrId);
H5A.info_t attrInfo = new H5A.info_t();
var info_result = H5A.get_info(attrId, ref attrInfo);

// Note sure if this `size` is useful.
// Docs say: For variable-length string datatypes, the returned value is
//           the size of the pointer to the actual string, or sizeof(char *). 
//           This function does not return the size of actual variable-length
//           string data.
// @See: https://support.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-GetSize
int size = H5T.get_size(typeId).ToInt32();

// Docs say: `data_size` indicates the size, in the number of characters,
//           of the attribute.
// @See: https://support.hdfgroup.org/HDF5/doc/RM/RM_H5A.html#Annot-GetInfo
int data_size = (int)attrInfo.data_size;

// Docs say: In a C environment, variable-length strings will always be
//           NULL-terminated, so the buffer to hold such a string must be
//           one byte larger than the string itself to accommodate the NULL
//           terminator.
// @See: https://support.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#CreateVLString
IntPtr iPtr = Marshal.AllocHGlobal(data_size + 1); // Add one to fit NULL-terminator.

int read_result = H5A.read(attrId, typeId, iPtr);
if (H5T.is_variable_str(typeId) > 0)
{
  Console.WriteLine("attribute value = {0}", Marshal.PtrToStringAnsi(iPtr));
}

控制台输出随机数据:

代码语言:javascript
复制
attribute value = @Ñ>←
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-24 10:14:05

我从Hdf5DotnetTools库中找到了一个解决方案。

代码语言:javascript
复制
long fileId = H5F.open("my-file.h5", H5F.ACC_RDWR);
long attrId = H5A.open(fileId, "foo");
long typeId = H5A.get_type(attrId);
long spaceId = H5A.get_space(attrId);
long count = H5S.get_simple_extent_npoints(spaceId);
H5S.close(spaceId);

IntPtr[] dest = new IntPtr[count];
GCHandle handle = GCHandle.Alloc(dest, GCHandleType.Pinned);
H5A.read(attrId, typeId, handle.AddrOfPinnedObject());

var attrStrings = new List<string>();
for (int i = 0; i < dest.Length; ++i)
{
    int attrLength = 0;
    while (Marshal.ReadByte(dest[i], attrLength) != 0)
    {
        ++attrLength;
    }

    byte[] buffer = new byte[attrLength];
    Marshal.Copy(dest[i], buffer, 0, buffer.Length);
    string stringPart = Encoding.UTF8.GetString(buffer);

    attrStrings.Add(stringPart);

    H5.free_memory(dest[i]);
}

handle.Free();

if (H5T.is_variable_str(typeId) > 0)
{
    Console.WriteLine("attribute value = {0}", attrStrings[0]);
}

控制台输出正确:

代码语言:javascript
复制
attribute value = bar
票数 1
EN

Stack Overflow用户

发布于 2018-08-23 16:49:17

看一下HDFql,因为在C#中处理HDF可变长度字符串时,这将使您摆脱底层细节的困扰。下面是一个关于如何使用HDFql读取(和打印)属性中存储的可变长度字符串的完整示例(假设存在一个名为my-file.h5的HDF文件,并且它包含一个可变长度字符串的属性foo ):

代码语言:javascript
复制
// use HDFql namespace (make sure it can be found by the C# compiler)
using AS.HDFql;

public class Example
{
    public static void Main(string []args)
    {
        // select (i.e. read) attribute "foo" (from HDF5 file "my-file.h5") and populate default cursor with its data
        HDFql.Execute("SELECT FROM my-file.h5 foo");

        // move default cursor to first position
        HDFql.CursorFirst();
        
        // display content of default cursor
        System.Console.WriteLine(HDFql.CursorGetChar());
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51978853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档