Writing a string array as attribute (in Fortran)


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!


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:


    ! 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)


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 :face_with_raised_eyebrow: 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)
    ! create dataset
    call h5dcreate_f (h5_file, trim (name), h5_strtype, h5_dspace, h5_dset, h5_err)
  ! 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,