Reading string attributes in hdf5 w/ vb.net

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

···

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

···

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,

···

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

William,

This works for me. Its somewhat of a pain, so I wrote a helper method in a static class. It also uses a separate class for working with variable length strings (if you need that).

Jesse

/// <summary>
/// Helper class for working with HDF5 files.
/// </summary>
public static class Hdf5Helper
{
public static string ReadAttributeString(H5ObjectWithAttributes groupId, string objectName, string attributeName)
     {
H5AttributeId attributeId = null;
H5DataTypeId dataTypeId = null;
// Read the Type attribute
try
         {
             attributeId = H5A.openByName(groupId, objectName, attributeName);
             dataTypeId = H5A.getType(attributeId);
bool isVariableLength = H5T.isVariableString(dataTypeId);

if (isVariableLength)
             {
// Variable length string attribute
// NOTE: This section only works if the array length is 1
VariableLengthString value = new VariableLengthString[1];
H5A.read<VariableLengthString>(attributeId, dataTypeId, new H5Array<VariableLengthString>(value));

return value[0].ToString();
                 }
else
             {
// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

// Fixed length string attribute
byte valueBytes = new byte[length];

H5A.read<byte>(attributeId, dataTypeId, new H5Array<byte>(valueBytes));
string value = System.Text.ASCIIEncoding.ASCII.GetString(valueBytes);

return value;
             }
         }
catch (H5AopenByNameException)
         {
// Attribute does not exist
         }
catch (H5AreadException)
         {
// Could not read the attribute correctly
         }
finally
         {
if (dataTypeId != null)
             {
H5T.close(dataTypeId);
             }
if (attributeId != null)
             {
H5A.close(attributeId);
             }
         }
return null;
     }
}

/// <summary>
/// Struct used to read in variable length string data from an HDF5
/// file. It is unsafe, therefore, the layout is used to define the
/// struct.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct VariableLengthString
{
/// <summary>
/// Pointer to the variable length string
/// </summary>
private char* recordedText;

/// <summary>
/// Gets or sets the pointer to the variable length string.
/// </summary>
     [CLSCompliant(false)]
public char* RecordedText
     {
get
         {
return this.recordedText;
         }

set
         {
this.recordedText = value;
         }
     }

/// <summary>
/// Returns a System.String that represents the current System.Object.
/// </summary>
/// <returns>The value of the variable length string.</returns>
public override string ToString()
     {
string s;

// The HDF5 STRING is not a string but in fact a char*
// Therefore, we need to translate the return into a pointer address
IntPtr ipp = (IntPtr)this.recordedText;

// This call is used to transform the pointer into the value of the pointer.
// NOTE: this only works with null-terminated strings.
         s = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ipp);

//// FREE THE MEMORY TO THE POINTER??
//// System.Runtime.InteropServices.Marshal.FreeHGlobal(ipp);

return s;
     }
}

···

On 7/23/2010 1:25 PM, whubler@as.arizona.edu wrote:

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,
--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

Hello Jesse,

I tried your code and got it to work, mostly. I couldn't make a straight
conversion to VB.net due to some pointer issues so I just put your code into a
dll and called it directly. The only problem I have now is that returned
string is missing the last character. I tried increasing the buffer but to no
avail. When I inspect the string before it goes out I see that it contains the
null terminator "\0". What do I need to do to get the last character? When you
run your code, do you get all characters?

···

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

William,

This works for me. Its somewhat of a pain, so I wrote a helper method
in a static class. It also uses a separate class for working with
variable length strings (if you need that).

Jesse

/// <summary>
/// Helper class for working with HDF5 files.
/// </summary>
public static class Hdf5Helper
{
public static string ReadAttributeString(H5ObjectWithAttributes groupId,
string objectName, string attributeName)
     {
H5AttributeId attributeId = null;
H5DataTypeId dataTypeId = null;
// Read the Type attribute
try
         {
             attributeId = H5A.openByName(groupId, objectName,
attributeName);
             dataTypeId = H5A.getType(attributeId);
bool isVariableLength = H5T.isVariableString(dataTypeId);

if (isVariableLength)
             {
// Variable length string attribute
// NOTE: This section only works if the array length is 1
VariableLengthString value = new VariableLengthString[1];
H5A.read<VariableLengthString>(attributeId, dataTypeId, new
H5Array<VariableLengthString>(value));

return value[0].ToString();
                 }
else
             {
// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

// Fixed length string attribute
byte valueBytes = new byte[length];

H5A.read<byte>(attributeId, dataTypeId, new H5Array<byte>(valueBytes));
string value = System.Text.ASCIIEncoding.ASCII.GetString(valueBytes);

return value;
             }
         }
catch (H5AopenByNameException)
         {
// Attribute does not exist
         }
catch (H5AreadException)
         {
// Could not read the attribute correctly
         }
finally
         {
if (dataTypeId != null)
             {
H5T.close(dataTypeId);
             }
if (attributeId != null)
             {
H5A.close(attributeId);
             }
         }
return null;
     }
}

/// <summary>
/// Struct used to read in variable length string data from an HDF5
/// file. It is unsafe, therefore, the layout is used to define the
/// struct.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct VariableLengthString
{
/// <summary>
/// Pointer to the variable length string
/// </summary>
private char* recordedText;

/// <summary>
/// Gets or sets the pointer to the variable length string.
/// </summary>
     [CLSCompliant(false)]
public char* RecordedText
     {
get
         {
return this.recordedText;
         }

set
         {
this.recordedText = value;
         }
     }

/// <summary>
/// Returns a System.String that represents the current System.Object.
/// </summary>
/// <returns>The value of the variable length string.</returns>
public override string ToString()
     {
string s;

// The HDF5 STRING is not a string but in fact a char*
// Therefore, we need to translate the return into a pointer address
IntPtr ipp = (IntPtr)this.recordedText;

// This call is used to transform the pointer into the value of the pointer.
// NOTE: this only works with null-terminated strings.
         s = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ipp);

//// FREE THE MEMORY TO THE POINTER??
//// System.Runtime.InteropServices.Marshal.FreeHGlobal(ipp);

return s;
     }
}

On 7/23/2010 1:25 PM, whubler@as.arizona.edu wrote:

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,
-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

I do get all the characters.

It might be this line:

// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

Did you try removing the subtraction of 1 to see if that works for you. I needed it I think because I didn't want the null terminator.

Jesse

···

On 7/24/2010 5:48 PM, whubler@as.arizona.edu wrote:

Hello Jesse,

I tried your code and got it to work, mostly. I couldn't make a straight
conversion to VB.net due to some pointer issues so I just put your code into a
dll and called it directly. The only problem I have now is that returned
string is missing the last character. I tried increasing the buffer but to no
avail. When I inspect the string before it goes out I see that it contains the
null terminator "\0". What do I need to do to get the last character? When you
run your code, do you get all characters?

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

William,

This works for me. Its somewhat of a pain, so I wrote a helper method
in a static class. It also uses a separate class for working with
variable length strings (if you need that).

Jesse

/// <summary>
/// Helper class for working with HDF5 files.
/// </summary>
public static class Hdf5Helper
{
public static string ReadAttributeString(H5ObjectWithAttributes groupId,
string objectName, string attributeName)
     {
H5AttributeId attributeId = null;
H5DataTypeId dataTypeId = null;
// Read the Type attribute
try
         {
             attributeId = H5A.openByName(groupId, objectName,
attributeName);
             dataTypeId = H5A.getType(attributeId);
bool isVariableLength = H5T.isVariableString(dataTypeId);

if (isVariableLength)
             {
// Variable length string attribute
// NOTE: This section only works if the array length is 1
VariableLengthString value = new VariableLengthString[1];
H5A.read<VariableLengthString>(attributeId, dataTypeId, new
H5Array<VariableLengthString>(value));

return value[0].ToString();
                 }
else
             {
// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

// Fixed length string attribute
byte valueBytes = new byte[length];

H5A.read<byte>(attributeId, dataTypeId, new H5Array<byte>(valueBytes));
string value = System.Text.ASCIIEncoding.ASCII.GetString(valueBytes);

return value;
             }
         }
catch (H5AopenByNameException)
         {
// Attribute does not exist
         }
catch (H5AreadException)
         {
// Could not read the attribute correctly
         }
finally
         {
if (dataTypeId != null)
             {
H5T.close(dataTypeId);
             }
if (attributeId != null)
             {
H5A.close(attributeId);
             }
         }
return null;
     }
}

/// <summary>
/// Struct used to read in variable length string data from an HDF5
/// file. It is unsafe, therefore, the layout is used to define the
/// struct.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct VariableLengthString
{
/// <summary>
/// Pointer to the variable length string
/// </summary>
private char* recordedText;

/// <summary>
/// Gets or sets the pointer to the variable length string.
/// </summary>
     [CLSCompliant(false)]
public char* RecordedText
     {
get
         {
return this.recordedText;
         }

set
         {
this.recordedText = value;
         }
     }

/// <summary>
/// Returns a System.String that represents the current System.Object.
/// </summary>
/// <returns>The value of the variable length string.</returns>
public override string ToString()
     {
string s;

// The HDF5 STRING is not a string but in fact a char*
// Therefore, we need to translate the return into a pointer address
IntPtr ipp = (IntPtr)this.recordedText;

// This call is used to transform the pointer into the value of the pointer.
// NOTE: this only works with null-terminated strings.
         s = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ipp);

//// FREE THE MEMORY TO THE POINTER??
//// System.Runtime.InteropServices.Marshal.FreeHGlobal(ipp);

return s;
     }
}

On 7/23/2010 1:25 PM, whubler@as.arizona.edu wrote:

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,
-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

Jesse,

That's what I thought as well, but when I took that off and even increased it I
still don't get the last character. I was able able to finally get it
translated to vb.net, at least your ReadAttributeString function with the same
results.

···

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

I do get all the characters.

It might be this line:

// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

Did you try removing the subtraction of 1 to see if that works for you.
I needed it I think because I didn't want the null terminator.

Jesse

On 7/24/2010 5:48 PM, whubler@as.arizona.edu wrote:

Hello Jesse,

I tried your code and got it to work, mostly. I couldn't make a straight
conversion to VB.net due to some pointer issues so I just put your code into a
dll and called it directly. The only problem I have now is that returned
string is missing the last character. I tried increasing the buffer but to no
avail. When I inspect the string before it goes out I see that it contains the
null terminator "\0". What do I need to do to get the last character? When you
run your code, do you get all characters?

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

William,

This works for me. Its somewhat of a pain, so I wrote a helper method
in a static class. It also uses a separate class for working with
variable length strings (if you need that).

Jesse

/// <summary>
/// Helper class for working with HDF5 files.
/// </summary>
public static class Hdf5Helper
{
public static string ReadAttributeString(H5ObjectWithAttributes groupId,
string objectName, string attributeName)
     {
H5AttributeId attributeId = null;
H5DataTypeId dataTypeId = null;
// Read the Type attribute
try
         {
             attributeId = H5A.openByName(groupId, objectName,
attributeName);
             dataTypeId = H5A.getType(attributeId);
bool isVariableLength = H5T.isVariableString(dataTypeId);

if (isVariableLength)
             {
// Variable length string attribute
// NOTE: This section only works if the array length is 1
VariableLengthString value = new VariableLengthString[1];
H5A.read<VariableLengthString>(attributeId, dataTypeId, new
H5Array<VariableLengthString>(value));

return value[0].ToString();
                 }
else
             {
// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

// Fixed length string attribute
byte valueBytes = new byte[length];

H5A.read<byte>(attributeId, dataTypeId, new H5Array<byte>(valueBytes));
string value = System.Text.ASCIIEncoding.ASCII.GetString(valueBytes);

return value;
             }
         }
catch (H5AopenByNameException)
         {
// Attribute does not exist
         }
catch (H5AreadException)
         {
// Could not read the attribute correctly
         }
finally
         {
if (dataTypeId != null)
             {
H5T.close(dataTypeId);
             }
if (attributeId != null)
             {
H5A.close(attributeId);
             }
         }
return null;
     }
}

/// <summary>
/// Struct used to read in variable length string data from an HDF5
/// file. It is unsafe, therefore, the layout is used to define the
/// struct.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct VariableLengthString
{
/// <summary>
/// Pointer to the variable length string
/// </summary>
private char* recordedText;

/// <summary>
/// Gets or sets the pointer to the variable length string.
/// </summary>
     [CLSCompliant(false)]
public char* RecordedText
     {
get
         {
return this.recordedText;
         }

set
         {
this.recordedText = value;
         }
     }

/// <summary>
/// Returns a System.String that represents the current System.Object.
/// </summary>
/// <returns>The value of the variable length string.</returns>
public override string ToString()
     {
string s;

// The HDF5 STRING is not a string but in fact a char*
// Therefore, we need to translate the return into a pointer address
IntPtr ipp = (IntPtr)this.recordedText;

// This call is used to transform the pointer into the value of the pointer.
// NOTE: this only works with null-terminated strings.
         s = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ipp);

//// FREE THE MEMORY TO THE POINTER??
//// System.Runtime.InteropServices.Marshal.FreeHGlobal(ipp);

return s;
     }
}

On 7/23/2010 1:25 PM, whubler@as.arizona.edu wrote:

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,
-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

Jesse,

OK, it looks like it might be the case of user error. I took a previous file
that had only numerical attributes , and in hdfview, I added in a string
attribute. One of the parameters was max string length, naturally I put in the
length of my string thinking it's not going to change. Looking at some previous
h5 files that do have string atts that I did not place, look to have, in
hdfview, a max length of +1 to the actual length of the string.

Now, armed with this knowledge, I have set about to new experiments. I reset
the max length to +1 in my file, and wouldn't you know it, your code works
flawlessly. Now onto other test files... hey look, it works again.

So in conclusion, I should have looked at the write function to see that +1 is
added to its length.

···

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

I do get all the characters.

It might be this line:

// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

Did you try removing the subtraction of 1 to see if that works for you.
I needed it I think because I didn't want the null terminator.

Jesse

On 7/24/2010 5:48 PM, whubler@as.arizona.edu wrote:

Hello Jesse,

I tried your code and got it to work, mostly. I couldn't make a straight
conversion to VB.net due to some pointer issues so I just put your code into a
dll and called it directly. The only problem I have now is that returned
string is missing the last character. I tried increasing the buffer but to no
avail. When I inspect the string before it goes out I see that it contains the
null terminator "\0". What do I need to do to get the last character? When you
run your code, do you get all characters?

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

William,

This works for me. Its somewhat of a pain, so I wrote a helper method
in a static class. It also uses a separate class for working with
variable length strings (if you need that).

Jesse

/// <summary>
/// Helper class for working with HDF5 files.
/// </summary>
public static class Hdf5Helper
{
public static string ReadAttributeString(H5ObjectWithAttributes groupId,
string objectName, string attributeName)
     {
H5AttributeId attributeId = null;
H5DataTypeId dataTypeId = null;
// Read the Type attribute
try
         {
             attributeId = H5A.openByName(groupId, objectName,
attributeName);
             dataTypeId = H5A.getType(attributeId);
bool isVariableLength = H5T.isVariableString(dataTypeId);

if (isVariableLength)
             {
// Variable length string attribute
// NOTE: This section only works if the array length is 1
VariableLengthString value = new VariableLengthString[1];
H5A.read<VariableLengthString>(attributeId, dataTypeId, new
H5Array<VariableLengthString>(value));

return value[0].ToString();
                 }
else
             {
// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

// Fixed length string attribute
byte valueBytes = new byte[length];

H5A.read<byte>(attributeId, dataTypeId, new H5Array<byte>(valueBytes));
string value = System.Text.ASCIIEncoding.ASCII.GetString(valueBytes);

return value;
             }
         }
catch (H5AopenByNameException)
         {
// Attribute does not exist
         }
catch (H5AreadException)
         {
// Could not read the attribute correctly
         }
finally
         {
if (dataTypeId != null)
             {
H5T.close(dataTypeId);
             }
if (attributeId != null)
             {
H5A.close(attributeId);
             }
         }
return null;
     }
}

/// <summary>
/// Struct used to read in variable length string data from an HDF5
/// file. It is unsafe, therefore, the layout is used to define the
/// struct.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct VariableLengthString
{
/// <summary>
/// Pointer to the variable length string
/// </summary>
private char* recordedText;

/// <summary>
/// Gets or sets the pointer to the variable length string.
/// </summary>
     [CLSCompliant(false)]
public char* RecordedText
     {
get
         {
return this.recordedText;
         }

set
         {
this.recordedText = value;
         }
     }

/// <summary>
/// Returns a System.String that represents the current System.Object.
/// </summary>
/// <returns>The value of the variable length string.</returns>
public override string ToString()
     {
string s;

// The HDF5 STRING is not a string but in fact a char*
// Therefore, we need to translate the return into a pointer address
IntPtr ipp = (IntPtr)this.recordedText;

// This call is used to transform the pointer into the value of the pointer.
// NOTE: this only works with null-terminated strings.
         s = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ipp);

//// FREE THE MEMORY TO THE POINTER??
//// System.Runtime.InteropServices.Marshal.FreeHGlobal(ipp);

return s;
     }
}

On 7/23/2010 1:25 PM, whubler@as.arizona.edu wrote:

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,
-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

William,

Well, I'm glad to hear you got it working.

Jesse

···

On 7/25/2010 2:02 AM, whubler@as.arizona.edu wrote:

Jesse,

OK, it looks like it might be the case of user error. I took a previous file
that had only numerical attributes , and in hdfview, I added in a string
attribute. One of the parameters was max string length, naturally I put in the
length of my string thinking it's not going to change. Looking at some previous
h5 files that do have string atts that I did not place, look to have, in
hdfview, a max length of +1 to the actual length of the string.

Now, armed with this knowledge, I have set about to new experiments. I reset
the max length to +1 in my file, and wouldn't you know it, your code works
flawlessly. Now onto other test files... hey look, it works again.

So in conclusion, I should have looked at the write function to see that +1 is
added to its length.

--
William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

I do get all the characters.

It might be this line:

// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

Did you try removing the subtraction of 1 to see if that works for you.
I needed it I think because I didn't want the null terminator.

Jesse

On 7/24/2010 5:48 PM, whubler@as.arizona.edu wrote:

Hello Jesse,

I tried your code and got it to work, mostly. I couldn't make a straight
conversion to VB.net due to some pointer issues so I just put your code into a
dll and called it directly. The only problem I have now is that returned
string is missing the last character. I tried increasing the buffer but to no
avail. When I inspect the string before it goes out I see that it contains the
null terminator "\0". What do I need to do to get the last character? When you
run your code, do you get all characters?

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Jesse Lai <jlai.matlab@gmail.com>:

William,

This works for me. Its somewhat of a pain, so I wrote a helper method
in a static class. It also uses a separate class for working with
variable length strings (if you need that).

Jesse

/// <summary>
/// Helper class for working with HDF5 files.
/// </summary>
public static class Hdf5Helper
{
public static string ReadAttributeString(H5ObjectWithAttributes groupId,
string objectName, string attributeName)
     {
H5AttributeId attributeId = null;
H5DataTypeId dataTypeId = null;
// Read the Type attribute
try
         {
             attributeId = H5A.openByName(groupId, objectName,
attributeName);
             dataTypeId = H5A.getType(attributeId);
bool isVariableLength = H5T.isVariableString(dataTypeId);

if (isVariableLength)
             {
// Variable length string attribute
// NOTE: This section only works if the array length is 1
VariableLengthString value = new VariableLengthString[1];
H5A.read<VariableLengthString>(attributeId, dataTypeId, new
H5Array<VariableLengthString>(value));

return value[0].ToString();
                 }
else
             {
// Make length smaller so null termination character is not read
int length = (int)H5T.getSize(dataTypeId) - 1;

// Fixed length string attribute
byte valueBytes = new byte[length];

H5A.read<byte>(attributeId, dataTypeId, new H5Array<byte>(valueBytes));
string value = System.Text.ASCIIEncoding.ASCII.GetString(valueBytes);

return value;
             }
         }
catch (H5AopenByNameException)
         {
// Attribute does not exist
         }
catch (H5AreadException)
         {
// Could not read the attribute correctly
         }
finally
         {
if (dataTypeId != null)
             {
H5T.close(dataTypeId);
             }
if (attributeId != null)
             {
H5A.close(attributeId);
             }
         }
return null;
     }
}

/// <summary>
/// Struct used to read in variable length string data from an HDF5
/// file. It is unsafe, therefore, the layout is used to define the
/// struct.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct VariableLengthString
{
/// <summary>
/// Pointer to the variable length string
/// </summary>
private char* recordedText;

/// <summary>
/// Gets or sets the pointer to the variable length string.
/// </summary>
     [CLSCompliant(false)]
public char* RecordedText
     {
get
         {
return this.recordedText;
         }

set
         {
this.recordedText = value;
         }
     }

/// <summary>
/// Returns a System.String that represents the current System.Object.
/// </summary>
/// <returns>The value of the variable length string.</returns>
public override string ToString()
     {
string s;

// The HDF5 STRING is not a string but in fact a char*
// Therefore, we need to translate the return into a pointer address
IntPtr ipp = (IntPtr)this.recordedText;

// This call is used to transform the pointer into the value of the pointer.
// NOTE: this only works with null-terminated strings.
         s = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ipp);

//// FREE THE MEMORY TO THE POINTER??
//// System.Runtime.InteropServices.Marshal.FreeHGlobal(ipp);

return s;
     }
}

On 7/23/2010 1:25 PM, whubler@as.arizona.edu wrote:

Ruth,

That I have tried and although I got the string dataset to work in C#, I was not
able to get it to work with string attributes in C#. When converted to VB I am
unable to direct cast a pointer to an intptr. Is is just a deficiency in the
dotnet wrappers?

Thanks,
-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

Quoting Ruth Aydt <aydt@hdfgroup.org>:

You might take a look at the user-contributed example for reading variable-length strings that is found here:

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

On Jul 23, 2010, at 11:43 AM, whubler@as.arizona.edu wrote:

Hello all,

It seems that I have hit a wall here. I have a program that reads h5 files.
Datasets (numerical), groups and attributes (numerical), I can read fine. I
now have some string attributes to read.

I have tried:

Dim fileId As H5FileId = H5F.open('f:\newDataFormat.h5", H5F.OpenMode.ACC_RDWR)
Dim dsetId As H5DataSetId = H5D.open(fileId,"units")
Dim attrId As H5AttributeId = H5A.open(dsetId, "unit")
Dim strtype As New H5DataTypeId(H5T.H5Type.C_S1)
Dim read_data As string() = New string(0) {}
H5A.read(attrId, strtype, New H5Array(Of string)(read_data))

and when I look at read_data(0), it is nothing. I also get no errors.

I can make this work for integers, doubles and the like, but not strings. Am I
missing something.

I am using VS 2008, vb.net, XP 64 bit and the .net hdf5 wrappers after making
them work for 64bit.

Any help would be greatly appreciated.

Thanks,

-- William Hubler
Technical Services Specialist
Steward Observatory Mirror Lap
University of Arizona

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

_______________________________________________
Hdf-forum is for HDF software users discussion.
Hdf-forum@hdfgroup.org
http://mail.hdfgroup.org/mailman/listinfo/hdf-forum_hdfgroup.org

hello
can you share the vbnet please ?
thanks

This is the code to read HDF5 in VB.net

Sub ReadHDF()
’ Specify the path to your HDF5 file
Dim filePath As String = “Filename+path”

   ' Open the HDF5 file
   Dim fileId As H5FileId = H5F.open(filePath, H5F.OpenMode.ACC_RDONLY)

   ' Specify the dataset name you want to read
   Dim datasetName As String = "/path/to/dataset"



   ' Open the dataset
   Dim datasetId As H5DataSetId = H5D.open(fileId, datasetName)

   ' Get the dataspace of the dataset
   Dim spaceId As H5DataSpaceId = H5D.getSpace(datasetId)

   ' Get the dimensions of the dataset
   Dim dims() As Long = H5S.getSimpleExtentDims(spaceId)

   ' Create an array to hold the data
   Dim data(dims(0) - 1, dims(1) - 1) As Double

   ' Read the data from the dataset
   H5D.read(datasetId, New H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE), New H5Array(Of Double)(data))

   ' Close the dataset, dataspace, and file
   H5D.close(datasetId)
   H5S.close(spaceId)
   H5F.close(fileId)

   ' Output the data to the console (for demonstration)
   For i As Integer = 0 To dims(0) - 1
       For j As Integer = 0 To dims(1) - 1
           Console.Write(data(i, j).ToString() & " ")

           MsgBox(data(i, j).ToString() & " ")

       Next

       'MsgBox(data(i, j))


       'Console.WriteLine()
   Next

End Sub

’ Function to initialize an array based on rank and dimensions
Function InitializeArray(rank As Integer, dims As Long()) As Array
Select Case rank
Case 1
Return Array.CreateInstance(GetType(Double), dims(0))
Case 2
Return Array.CreateInstance(GetType(Double), dims(0), dims(1))
Case 3
Return Array.CreateInstance(GetType(Double), dims(0), dims(1), dims(2))
Case Else
Throw New NotSupportedException("Unsupported dataset rank: " & rank)
End Select
End Function

’ Function to print the array contents
Sub PrintArray(data As Array)
If data.Rank = 1 Then
’ Print 1D array
For i As Integer = 0 To data.GetLength(0) - 1
Console.Write(data.GetValue(i).ToString() & " ")
Next
Console.WriteLine()
ElseIf data.Rank = 2 Then
’ Print 2D array
For i As Integer = 0 To data.GetLength(0) - 1
For j As Integer = 0 To data.GetLength(1) - 1
Console.Write(data.GetValue(i, j).ToString() & " ")
Next
Console.WriteLine()
Next
ElseIf data.Rank = 3 Then
’ Print 3D array
For i As Integer = 0 To data.GetLength(0) - 1
For j As Integer = 0 To data.GetLength(1) - 1
For k As Integer = 0 To data.GetLength(2) - 1
Console.Write(data.GetValue(i, j, k).ToString() & " ")
Next
Console.WriteLine()
Next
Console.WriteLine()
Next
Else
Console.WriteLine("Unsupported array rank: " & data.Rank)
End If
End Sub