Hi,
I’m trying to write an array of strings as attribute into a .h5 file in Fortran. Something like:
animals = (/ ‘dog’, ‘duck’, ‘horse’ /)
Can I do it using h5ltset_attribute_string_f in a similar way in which I am storing an array of integers:
CALL h5ltset_attribute_int_f(file_id, “/”, “dimensions”, dimensions, 4*size_attribute, error)
Could you please give me an example of code? I apologize if this question is too simple for this forum.
Many thanks!
NV
Hi @nikola.vitas.iac,
Not sure how this is done with the Fortran API you are using but with HDFql, a high-level programming language to manage HDF5 files, writing an array of (fixed-length) strings into an attribute could be done as follows in Fortran:
PROGRAM Example
! use HDFql module (make sure it can be found by the Fortran compiler)
USE HDFql
! declare variables
CHARACTER(LEN = 5), DIMENSION(3) :: strings = [CHARACTER(LEN = 5) :: "dog", "duck", "horse"]
CHARACTER :: variable_number
INTEGER :: state
! create an HDF5 file named "example.h5" and use (i.e. open) it
state = hdfql_execute("CREATE AND USE FILE example.h5")
! create an attribute named "my_attribute" of type char (size 5) of one dimension (size 3)
state = hdfql_execute("CREATE ATTRIBUTE my_attribute AS CHAR(3, 5)");
! register variable "strings" for subsequent use (by HDFql)
state = hdfql_variable_register(strings)
WRITE(variable_number, "(I0)") state
! insert (i.e. write) content of variable "strings" into attribute "my_attribute"
state = hdfql_execute("INSERT INTO my_attribute VALUES FROM MEMORY " // variable_number)
END PROGRAM
Hope this helps!
It would not be h5ltset_attribute_string_f since that is expecting a scalar. It should be H5LTset_attribute_f, but I looked and, well, it calls h5ltset_attribute_string
So that function can not handle an array of characters. You need to use the low-level APIs, have a look at https://support.hdfgroup.org/HDF5/examples/api-fortran.html
example: h5ex_t_stringCatt_F03.f90
You don’t have to write a C string, you can ignore that part (i.e. H5T) of the example
Many thanks! I will certainly explore HDFql, but I would prefer to avoid high-level libraries, as my writing routine is part of a huge parallel code that needs to be portable to very different machines (and hopefully stable for long time, with different compilers, etc).
Thank you, @brtnfld! I guess that a quick workaround could be to merge the string array into one string with some delimiters. And then to parse the string after reading it. It’s not very elegant, but it should be easy to implement.
I’m surprised that there is no standard function for something like this. It doesn’t sound like an exotic case.
Dear Nikola!
Sorry, I saw your request only now. I have solved this problem in Pencil Code like this:
subroutine output_hdf5_string(name, data)
character (len=*), intent(in) :: name
character (len=*), intent(in) :: data
integer(HID_T) :: h5_strtype
integer(HSIZE_T), dimension(2) :: size
character (len=len(data)+1), dimension(1) :: str_data
integer(SIZE_T), dimension(1) :: str_len
! string output requires to open a file local = non-parallel
str_len(1) = len_trim (data)
size(1) = str_len(1)
size(2) = 1
str_data(1) = data//char(0)
! create data space
call H5Tcopy_f (H5T_STRING, h5_strtype, h5_err)
call H5Tset_strpad_f (h5_strtype, H5T_STR_NULLPAD_F, h5_err)
call h5screate_simple_f (1, size(2), h5_dspace, h5_err)
if (exists_in_hdf5 (name)) then
! open dataset
call h5dopen_f (h5_file, trim (name), h5_dset, h5_err)
else
! create dataset
call h5dcreate_f (h5_file, trim (name), h5_strtype, h5_dspace, h5_dset, h5_err)
endif
! write dataset
call h5dwrite_vl_f (h5_dset, h5_strtype, str_data, size, str_len, h5_err, h5_dspace)
! close dataset and data space
call h5dclose_f (h5_dset, h5_err)
call h5sclose_f (h5_dspace, h5_err)
endsubroutine output_hdf5_string
Of course you should check the error status ‘h5_err’ after each instruction…
Best greetings,
Philippe.