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