1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * Copyright by The HDF Group. * 3 * Copyright by the Board of Trustees of the University of Illinois. * 4 * All rights reserved. * 5 * * 6 * This file is part of HDF5. The full HDF5 copyright notice, including * 7 * terms governing use, modification, and redistribution, is contained in * 8 * the COPYING file, which can be found at the root of the source code * 9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * 10 * If you do not have access to either file, you may request a copy from * 11 * help@hdfgroup.org. * 12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 13 14 /************************************************************ 15 This example shows how to read and write compound 16 datatypes to a dataset. The program first writes 17 compound structures to a dataset with a dataspace of DIM0, 18 then closes the file. Next, it reopens the file, reads 19 back the data, and outputs it to the screen. 20 ************************************************************/ 21 22 package examples.datatypes; 23 24 import hdf.hdf5lib.H5; 25 import hdf.hdf5lib.HDF5Constants; 26 27 import java.nio.ByteBuffer; 28 import java.nio.ByteOrder; 29 import java.nio.charset.Charset; 30 31 public class H5Ex_T_Compound { 32 private static String FILENAME = "H5Ex_T_Compound.h5"; 33 private static String DATASETNAME = "DS1"; 34 private static final int DIM0 = 4; 35 private static final int RANK = 1; 36 protected static final int INTEGERSIZE = 4; 37 protected static final int DOUBLESIZE = 8; 38 protected final static int MAXSTRINGSIZE = 80; 39 40 static class Sensor_Datatype { 41 static int numberMembers = 4; 42 static int[] memberDims = { 1, 1, 1, 1 }; 43 44 static String[] memberNames = { "Serial number", "Location", "Temperature (F)", "Pressure (inHg)" }; 45 static long[] memberMemTypes = { HDF5Constants.H5T_NATIVE_INT, HDF5Constants.H5T_C_S1, 46 HDF5Constants.H5T_NATIVE_DOUBLE, HDF5Constants.H5T_NATIVE_DOUBLE }; 47 static long[] memberFileTypes = { HDF5Constants.H5T_STD_I32BE, HDF5Constants.H5T_C_S1, 48 HDF5Constants.H5T_IEEE_F64BE, HDF5Constants.H5T_IEEE_F64BE }; 49 static int[] memberStorage = { INTEGERSIZE, MAXSTRINGSIZE, DOUBLESIZE, DOUBLESIZE }; 50 51 // Data size is the storage size for the members. getTotalDataSize()52 static long getTotalDataSize() { 53 long data_size = 0; 54 for (int indx = 0; indx < numberMembers; indx++) 55 data_size += memberStorage[indx] * memberDims[indx]; 56 return DIM0 * data_size; 57 } 58 getDataSize()59 static long getDataSize() { 60 long data_size = 0; 61 for (int indx = 0; indx < numberMembers; indx++) 62 data_size += memberStorage[indx] * memberDims[indx]; 63 return data_size; 64 } 65 getOffset(int memberItem)66 static int getOffset(int memberItem) { 67 int data_offset = 0; 68 for (int indx = 0; indx < memberItem; indx++) 69 data_offset += memberStorage[indx]; 70 return data_offset; 71 } 72 } 73 74 static class Sensor { 75 public int serial_no; 76 public String location; 77 public double temperature; 78 public double pressure; 79 Sensor(int serial_no, String location, double temperature, double pressure)80 Sensor(int serial_no, String location, double temperature, double pressure) { 81 this.serial_no = serial_no; 82 this.location = location; 83 this.temperature = temperature; 84 this.pressure = pressure; 85 } 86 Sensor(ByteBuffer databuf, int dbposition)87 Sensor(ByteBuffer databuf, int dbposition) { 88 readBuffer(databuf, dbposition); 89 } 90 writeBuffer(ByteBuffer databuf, int dbposition)91 void writeBuffer(ByteBuffer databuf, int dbposition) { 92 databuf.putInt(dbposition + Sensor_Datatype.getOffset(0), serial_no); 93 byte[] temp_str = location.getBytes(Charset.forName("UTF-8")); 94 int arraylen = (temp_str.length > MAXSTRINGSIZE) ? MAXSTRINGSIZE : temp_str.length; 95 for (int ndx = 0; ndx < arraylen; ndx++) 96 databuf.put(dbposition + Sensor_Datatype.getOffset(1) + ndx, temp_str[ndx]); 97 for (int ndx = arraylen; ndx < MAXSTRINGSIZE; ndx++) 98 databuf.put(dbposition + Sensor_Datatype.getOffset(1) + arraylen, (byte) 0); 99 databuf.putDouble(dbposition + Sensor_Datatype.getOffset(2), temperature); 100 databuf.putDouble(dbposition + Sensor_Datatype.getOffset(3), pressure); 101 } 102 readBuffer(ByteBuffer databuf, int dbposition)103 void readBuffer(ByteBuffer databuf, int dbposition) { 104 this.serial_no = databuf.getInt(dbposition + Sensor_Datatype.getOffset(0)); 105 ByteBuffer stringbuf = databuf.duplicate(); 106 stringbuf.position(dbposition + Sensor_Datatype.getOffset(1)); 107 stringbuf.limit(dbposition + Sensor_Datatype.getOffset(1) + MAXSTRINGSIZE); 108 byte[] bytearr = new byte[stringbuf.remaining()]; 109 stringbuf.get(bytearr); 110 this.location = new String(bytearr, Charset.forName("UTF-8")).trim(); 111 this.temperature = databuf.getDouble(dbposition + Sensor_Datatype.getOffset(2)); 112 this.pressure = databuf.getDouble(dbposition + Sensor_Datatype.getOffset(3)); 113 } 114 115 @Override toString()116 public String toString() { 117 return String.format("Serial number : " + serial_no + "%n" + 118 "Location : " + location + "%n" + 119 "Temperature (F) : " + temperature + "%n" + 120 "Pressure (inHg) : " + pressure + "%n"); 121 } 122 } 123 CreateDataset()124 private static void CreateDataset() { 125 long file_id = -1; 126 long strtype_id = -1; 127 long memtype_id = -1; 128 long filetype_id = -1; 129 long dataspace_id = -1; 130 long dataset_id = -1; 131 long[] dims = { DIM0 }; 132 Sensor[] object_data = new Sensor[DIM0]; 133 byte[] dset_data = null; 134 135 // Initialize data. 136 object_data[0] = new Sensor(1153, new String("Exterior (static)"), 53.23, 24.57); 137 object_data[1] = new Sensor(1184, new String("Intake"), 55.12, 22.95); 138 object_data[2] = new Sensor(1027, new String("Intake manifold"), 103.55, 31.23); 139 object_data[3] = new Sensor(1313, new String("Exhaust manifold"), 1252.89, 84.11); 140 141 // Create a new file using default properties. 142 try { 143 file_id = H5.H5Fcreate(FILENAME, HDF5Constants.H5F_ACC_TRUNC, HDF5Constants.H5P_DEFAULT, 144 HDF5Constants.H5P_DEFAULT); 145 } 146 catch (Exception e) { 147 e.printStackTrace(); 148 } 149 150 // Create string datatype. 151 try { 152 strtype_id = H5.H5Tcopy(HDF5Constants.H5T_C_S1); 153 if (strtype_id >= 0) 154 H5.H5Tset_size(strtype_id, MAXSTRINGSIZE); 155 } 156 catch (Exception e) { 157 e.printStackTrace(); 158 } 159 160 // Create the compound datatype for memory. 161 try { 162 memtype_id = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, Sensor_Datatype.getDataSize()); 163 if (memtype_id >= 0) { 164 for (int indx = 0; indx < Sensor_Datatype.numberMembers; indx++) { 165 long type_id = Sensor_Datatype.memberMemTypes[indx]; 166 if (type_id == HDF5Constants.H5T_C_S1) 167 type_id = strtype_id; 168 H5.H5Tinsert(memtype_id, Sensor_Datatype.memberNames[indx], Sensor_Datatype.getOffset(indx), 169 type_id); 170 } 171 } 172 } 173 catch (Exception e) { 174 e.printStackTrace(); 175 } 176 177 // Create the compound datatype for the file. Because the standard 178 // types we are using for the file may have different sizes than 179 // the corresponding native types, we must manually calculate the 180 // offset of each member. 181 try { 182 filetype_id = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, Sensor_Datatype.getDataSize()); 183 if (filetype_id >= 0) { 184 for (int indx = 0; indx < Sensor_Datatype.numberMembers; indx++) { 185 long type_id = Sensor_Datatype.memberFileTypes[indx]; 186 if (type_id == HDF5Constants.H5T_C_S1) 187 type_id = strtype_id; 188 H5.H5Tinsert(filetype_id, Sensor_Datatype.memberNames[indx], Sensor_Datatype.getOffset(indx), 189 type_id); 190 } 191 } 192 } 193 catch (Exception e) { 194 e.printStackTrace(); 195 } 196 197 // Create dataspace. Setting maximum size to NULL sets the maximum 198 // size to be the current size. 199 try { 200 dataspace_id = H5.H5Screate_simple(RANK, dims, null); 201 } 202 catch (Exception e) { 203 e.printStackTrace(); 204 } 205 206 // Create the dataset. 207 try { 208 if ((file_id >= 0) && (dataspace_id >= 0) && (filetype_id >= 0)) 209 dataset_id = H5.H5Dcreate(file_id, DATASETNAME, filetype_id, dataspace_id, HDF5Constants.H5P_DEFAULT, 210 HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 211 } 212 catch (Exception e) { 213 e.printStackTrace(); 214 } 215 216 // Write the compound data to the dataset. 217 // allocate memory for read buffer. 218 dset_data = new byte[(int)dims[0] * (int)Sensor_Datatype.getDataSize()]; 219 ByteBuffer outBuf = ByteBuffer.wrap(dset_data); 220 outBuf.order(ByteOrder.nativeOrder()); 221 for (int indx = 0; indx < (int) dims[0]; indx++) { 222 object_data[indx].writeBuffer(outBuf, indx * (int)Sensor_Datatype.getDataSize()); 223 } 224 try { 225 if ((dataset_id >= 0) && (memtype_id >= 0)) 226 H5.H5Dwrite(dataset_id, memtype_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL, 227 HDF5Constants.H5P_DEFAULT, dset_data); 228 } 229 catch (Exception e) { 230 e.printStackTrace(); 231 } 232 233 // End access to the dataset and release resources used by it. 234 try { 235 if (dataset_id >= 0) 236 H5.H5Dclose(dataset_id); 237 } 238 catch (Exception e) { 239 e.printStackTrace(); 240 } 241 242 // Terminate access to the data space. 243 try { 244 if (dataspace_id >= 0) 245 H5.H5Sclose(dataspace_id); 246 } 247 catch (Exception e) { 248 e.printStackTrace(); 249 } 250 251 // Terminate access to the file type. 252 try { 253 if (filetype_id >= 0) 254 H5.H5Tclose(filetype_id); 255 } 256 catch (Exception e) { 257 e.printStackTrace(); 258 } 259 260 // Terminate access to the mem type. 261 try { 262 if (memtype_id >= 0) 263 H5.H5Tclose(memtype_id); 264 } 265 catch (Exception e) { 266 e.printStackTrace(); 267 } 268 269 try { 270 if (strtype_id >= 0) 271 H5.H5Tclose(strtype_id); 272 } 273 catch (Exception e) { 274 e.printStackTrace(); 275 } 276 277 // Close the file. 278 try { 279 if (file_id >= 0) 280 H5.H5Fclose(file_id); 281 } 282 catch (Exception e) { 283 e.printStackTrace(); 284 } 285 286 } 287 ReadDataset()288 private static void ReadDataset() { 289 long file_id = -1; 290 long strtype_id = -1; 291 long memtype_id = -1; 292 long dataspace_id = -1; 293 long dataset_id = -1; 294 long[] dims = { DIM0 }; 295 Sensor[] object_data2; 296 byte[] dset_data; 297 298 // Open an existing file. 299 try { 300 file_id = H5.H5Fopen(FILENAME, HDF5Constants.H5F_ACC_RDONLY, HDF5Constants.H5P_DEFAULT); 301 } 302 catch (Exception e) { 303 e.printStackTrace(); 304 } 305 306 // Open an existing dataset. 307 try { 308 if (file_id >= 0) 309 dataset_id = H5.H5Dopen(file_id, DATASETNAME, HDF5Constants.H5P_DEFAULT); 310 } 311 catch (Exception e) { 312 e.printStackTrace(); 313 } 314 315 // Get dataspace and allocate memory for read buffer. 316 try { 317 if (dataset_id >= 0) 318 dataspace_id = H5.H5Dget_space(dataset_id); 319 } 320 catch (Exception e) { 321 e.printStackTrace(); 322 } 323 324 try { 325 if (dataspace_id >= 0) 326 H5.H5Sget_simple_extent_dims(dataspace_id, dims, null); 327 } 328 catch (Exception e) { 329 e.printStackTrace(); 330 } 331 332 // Create string datatype. 333 try { 334 strtype_id = H5.H5Tcopy(HDF5Constants.H5T_C_S1); 335 if (strtype_id >= 0) 336 H5.H5Tset_size(strtype_id, MAXSTRINGSIZE); 337 } 338 catch (Exception e) { 339 e.printStackTrace(); 340 } 341 342 // Create the compound datatype for memory. 343 try { 344 memtype_id = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, Sensor_Datatype.getDataSize()); 345 if (memtype_id >= 0) { 346 for (int indx = 0; indx < Sensor_Datatype.numberMembers; indx++) { 347 long type_id = Sensor_Datatype.memberMemTypes[indx]; 348 if (type_id == HDF5Constants.H5T_C_S1) 349 type_id = strtype_id; 350 H5.H5Tinsert(memtype_id, Sensor_Datatype.memberNames[indx], Sensor_Datatype.getOffset(indx), 351 type_id); 352 } 353 } 354 } 355 catch (Exception e) { 356 e.printStackTrace(); 357 } 358 359 // allocate memory for read buffer. 360 dset_data = new byte[(int) dims[0] * (int)Sensor_Datatype.getDataSize()]; 361 362 object_data2 = new Sensor[(int) dims[0]]; 363 364 // Read data. 365 try { 366 if ((dataset_id >= 0) && (memtype_id >= 0)) 367 H5.H5Dread(dataset_id, memtype_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL, 368 HDF5Constants.H5P_DEFAULT, dset_data); 369 370 ByteBuffer inBuf = ByteBuffer.wrap(dset_data); 371 inBuf.order(ByteOrder.nativeOrder()); 372 for (int indx = 0; indx < (int) dims[0]; indx++) { 373 object_data2[indx] = new Sensor(inBuf, indx * (int)Sensor_Datatype.getDataSize()); 374 } 375 } 376 catch (Exception e) { 377 e.printStackTrace(); 378 } 379 380 // Output the data to the screen. 381 for (int indx = 0; indx < dims[0]; indx++) { 382 System.out.println(DATASETNAME + " [" + indx + "]:"); 383 System.out.println(object_data2[indx].toString()); 384 } 385 System.out.println(); 386 387 try { 388 if (dataset_id >= 0) 389 H5.H5Dclose(dataset_id); 390 } 391 catch (Exception e) { 392 e.printStackTrace(); 393 } 394 395 // Terminate access to the data space. 396 try { 397 if (dataspace_id >= 0) 398 H5.H5Sclose(dataspace_id); 399 } 400 catch (Exception e) { 401 e.printStackTrace(); 402 } 403 404 // Terminate access to the mem type. 405 try { 406 if (memtype_id >= 0) 407 H5.H5Tclose(memtype_id); 408 } 409 catch (Exception e) { 410 e.printStackTrace(); 411 } 412 413 try { 414 if (strtype_id >= 0) 415 H5.H5Tclose(strtype_id); 416 } 417 catch (Exception e) { 418 e.printStackTrace(); 419 } 420 421 // Close the file. 422 try { 423 if (file_id >= 0) 424 H5.H5Fclose(file_id); 425 } 426 catch (Exception e) { 427 e.printStackTrace(); 428 } 429 430 } 431 main(String[] args)432 public static void main(String[] args) { 433 H5Ex_T_Compound.CreateDataset(); 434 // Now we begin the read section of this example. Here we assume 435 // the dataset and array have the same name and rank, but can have 436 // any size. Therefore we must allocate a new array to read in 437 // data using malloc(). 438 H5Ex_T_Compound.ReadDataset(); 439 } 440 441 } 442