diff options
Diffstat (limited to 'doc/html/UsingC++.html')
-rw-r--r-- | doc/html/UsingC++.html | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/doc/html/UsingC++.html b/doc/html/UsingC++.html new file mode 100644 index 0000000..15622d0 --- /dev/null +++ b/doc/html/UsingC++.html @@ -0,0 +1,442 @@ +<html> + <head> + <title>IEEE IO C++ Interface</title> + </head> + <body bgcolor="#F0F0F0"> + <table><tr> + <td><img src="Images/info.gif"></td> + <td><h1>C++</h1></td> + </tr></table> + <hr> + <h1>Using the C++ Interface</h1> + To use the C++ interface, you must include the + headers <b>IO.hh</b> and <b>IEEEIO.hh</b>. If you only require + the IEEEIO interface, you link only with <b>libieeeio.a</b> using + <code>-L$IEEE_DIRECTORY/lib -lieeeio</code>.<p> + + If you + also want HDF support you must also include the header + <b>HDFIO.hh</b> and link with <b>libhdfio.a</b> and + the usual complement of HDF libraries using + <code>-L$HDF_DIRECTORY/lib -L$IEEE_DIRECTORY/lib -lhdfio + -lieeeio -lmfhdf -ldf -ljpeg -lz</code>. + <hr> + <h1>C++ Methods</h1> + <UL> + <LI><a href="#Opening">Opening and Closing Datafiles</a> + <LI><a href="#Writing">Writing Datasets</a> + <LI><a href="#Reading">Reading Datasets</a> + <LI><a href="#Seeking">Random Access to Datasets <i>(Seeking)</i></a> + <LI><a href="#WriteAttribs">Writing Attributes</a> + <LI><a href="#ReadAttribs">Reading Attributes</a> + <LI><a href="#WriteAnn">Writing Annotations</a> + <LI><a href="#ReadAnn">Reading Annotations</a> + <LI><a href="#ReadWriteChunk">Writing and Reading in Chunks</a> + </UL> + + <hr> + <a name="Opening"><h2>Opening</h2></a> + To open an IEEEIO file, you simply create a new IEEEIO object. + The constructor handles the opening.<p> + <b>C++ Prototype</b><br> + <code>IEEEIO::IEEEIO(char *filename,IObase::AccessMode accessmode);</code><br> + <DL> + <DT><i>filename</i>: + <DD>The name of the IEEEIO data file to + open. The typical extension for these files is <i>.raw</i> + <DT><i>accessmode</i>: + <DD>The accessmode for the file. This is + one of 3 different access modes + <!--<DL> + <DT><i>IObase::Read</i>: + <DD>Opens a file in read-only mode. + <DT><i>IObase::Create</i>: + <DD>Opens a file in write-only mode. If the file does not exist, it will be created. If it does exist, it will be truncated. + <DT><i>IObase::Append</i>: + <DD>Opens a file in read/write mode. The file pointer is automatically placed at the end of the file for appending, but random-access read operations are allowed as well. + </DL>--> + <UL> + <LI><b>IObase::Read</b>: + Opens a file in read-only mode. + <LI><b>IObase::Create</b>: + Opens a file in write-only mode. If the file does not exist, it will be created. If it does exist, it will be truncated. + <LI><b>IObase::Append</b>: + Opens a file in read/write mode. The file pointer is automatically placed at the end of the file for appending, but random-access read operations are allowed as well. + </UL> + </DL> + + Since this is inherited from the IO base class, you can assign + the newly created object to a pointer to the base class and + deal with it generically.<br> +<pre> + IO *writer = new IEEEIO("datafileout.raw",IObase::Create); + IO *reader = new IEEEIO("datafilein.raw",IObase::Read); +</pre><br> + You can test if the file was opened successfully using the IObase::isValid() method.<br> +<pre> + if(!reader->isValid()) + puts("The file you specified does not exist or is not in a readable format"); +</pre><br> + + Other IO systems can be inherited from the IO base class. So + for instance, to read HDF files you simply link with the the HDFIO + and HDF libraries and open using; + <pre> + IO *writer = new HDFIO("datafileout.raw",IObase::Create); + IO *reader = new HDFIO("datafilein.raw",IObase::Read); + </pre> + + After the files are opened, you can use the methods in the + baseclass IO to do all of your reading and writing in a completely + generic manner regardless of the implementation of the underlying + IO system so long as the underlying IO system implements the + methods of the base class. There are plans, for example, to have + a SocketIO system that allows the data to be written out to a TCP + socket instead of to a file for real-time simulation-visualization + systems. There are also plans to use this interface to drive an + existing Parallel IO system.<p> + +To close the file, you simply delete the object. +<pre> + delete writer; + delete reader; +</pre> + Since virtual destructors are used, you can delete them as + objects of the base IO class (no casts required). + + <hr> + <a name="Writing"><h2>Writing</h2></a> + To write data you simply use the method write(). + <p><b>C++ Prototype</b><br> + <code>IEEEIO::write(IObase::DataType numbertype,int rank,int *dimensions,void *data);</code> + <DL> + <DT><i>numbertype</i>: + <DD>The type of the data being stored + (as defined in <a href="DataTypes.html">DataType.html</a>). + It can be one of + <UL> + <LI><b>IObase::Float32</b><br><i>32-bit single-precision IEEE float</i> + <LI><b>IObase::Float64</b><br><i>64-bit double-precision IEEE float</i> + <LI><b>IObase::Int8</b><br><i>byte</i> + <LI><b>IObase::Int16</b><br><i>16-bit short integer</i> + <LI><b>IObase::Int32</b><br><i>32-bit standard integer</i> + <LI><b>IObase::Int64</b><br><i>64-bit long integer. (note: + this is not availible on the Intel/Windows + platform)</i> + <LI><b>IObase::uInt8</b><br><i>unsigned character</i> + <LI><b>IObase::uInt16</b><br><i>unsigned 16-bit short integer</i> + <LI><b>IObase::uInt32</b><br><i>unsigned 32-bit standard integer</i> + <LI><b>IObase::uInt64</b><br><i>unsigned 64-bit long integer. (note: this is not availible on the Intel/Windows platform)</i> + </UL> + <DT><i>rank</i> + <DD>Number of dimensions of the dataset + <DT><i>dimensions</i>: + <DD>An array of <i>rank</i> integers that give the dimensions of the dataset + <DT><i>data</i>: + <DD>Your data array. + </DL> + + So to write a sample array of data. + <pre> + float myarray[40][50][60]; // our bogus data array + int rank=3; + int dims[3]={60,50,40}; // notice these are reversed. + // this is because ieeeio assumes f77 order for data + // and c/c++ use exactly the opposite ordering for data in memory. + IO *writer=new IEEEIO("datafile.raw",IObase::Create); // create a outfile + writer->write(IObase::Float32,rank,dims,myarray); // write a dataset + . . . . you can write as many datasets as you want + delete writer; // then close the file + </pre> + + <hr> + <a name="Reading"><h2>Reading Data</h2></a> + Reading is a two step process. First you get information on + the size and type of the data you intend to read. This allows + you to allocate an array of the proper size and type for the + reading. Then you actually read the data into a pre-allocated + array. The methods for this are readInfo() and read().<p> + <b>C++ Prototype</b><br> + <code>readInfo(IObase::DataType &numbertype,int &rank,int + *dims,int maxdims=3);</code><p> + <DL> + <DT><i>numbertype</i>: + <DD>The type of the data being stored + <i>(<a href="DataTypes.html">datatype definition</a>)</i>. + It can be one of + <UL> + <LI><b>IObase::Float32</b><br><i>32-bit single-precision IEEE float</i> + <LI><b>IObase::Float64</b><br><i>64-bit double-precision IEEE float</i> + <LI><b>IObase::Int8</b><br><i>byte</i> + <LI><b>IObase::Int16</b><br><i>16-bit short integer</i> + <LI><b>IObase::Int32</b><br><i>32-bit standard integer</i> + <LI><b>IObase::Int64</b><br><i>64-bit long integer. (note: + this is not availible on the Intel/Windows + platform)</i> + <LI><b>IObase::uInt8</b><br><i>unsigned character</i> + <LI><b>IObase::uInt16</b><br><i>unsigned 16-bit short integer</i> + <LI><b>IObase::uInt32</b><br><i>unsigned 32-bit standard integer</i> + <LI><b>IObase::uInt64</b><br><i>unsigned 64-bit long integer. (note: this is not availible on the Intel/Windows platform)</i> + </UL> + <DT><i>rank</i> + <DD>Number of dimensions of the dataset + <DT><i>dimensions</i>: + <DD>An array of <i>rank</i> integers that give the dimensions + of the dataset + <DT><i>maxdims</i>: + <DD>The maximum size of the dimensions array you given it. + This prevents array overruns if the dataset has more + dimensions than you were anticipating. The default is 3 but + it can be any arbitrary positive integer. + </DL> + This retrieves information about the datatype, rank, + and dimensions of the dataset to be retrieved. + By default the maximum size of the dimensions array is 3, + but you can set it to be larger.<p> + <b>C++ Prototype</b><br> + <code> + IEEEIO::read(void *data); + </code><p> + This actually reads the dataset into the preallocated array <i>data</i>.<p> + + Another useful utility function is IObase::sizeOf() which returns the number of bytes in a give IObase:: datatype in manner analogous to the standard C sizeof() operator. + + So for instance, to read a simple dataset, you would do + <pre> + int rank; + IObase::DataType numbertype; + int dims[3]; + float *data; // assumes float data + IO *infile = new IEEEIO("dataset.raw",IObase::Read); + infile->readInfo(numbertype,rank,dims); + // OK, we are assuming a 3D IObase::Float32 array, + // but you can be more sophisticated... + data = new char[IObase::nBytes(numbertype,rank,dims)]; + // You can also use + // data = new float[IObase::nElements(rank,dims)]; + infile->read(data); // read in the data + </pre><p> + + Since multiple datasets can be stored in a file, you can + retrieve them in the order they were written <i>(there is a <a +href="#Seeking">seek()</a> function that allows random access as well)</i>. The method <b>readInfo()</b> implies reading the next dataset stored in the file. The method <b>nDatasets()</b> tells how many datasets are in a file. So typically if you want to read all datasets in a file in order, you would use code similar to; + <pre> + IO *infile = new IEEEIO("dataset.raw",IObase::Read); + for(int i=0;i<infile->nDatasets();i++){ + .....lots of code.... + infile->readInfo(numbertype,rank,dims); // increments to next dataset + .....more code.... + } + </pre> + + <hr> + <a name="Seeking"><h2>Random Access to Datasets + <i>(Seeking)</i></h2></a> + You can select specific datasets in a file using the seek() + method.<p> + <b>C++ Prototype</b> + <code>IEEEIO::seek(int index)</code> + <DL> + <DT><b>index</b> + <DD>The index of the dataset you want to read from. This can + be any number from 0 to (number_of_datasets - 1). + </DL> + + <hr> + <a name="WriteAttribs"><h2>Writing Attributes</h2></a> + Attributes allow you to attach extra information to each + dataset stored in the file. Each attribute has a name and an + array of data (of any of the standard IObase:: types) stored with + it. These attributes can be retrieved by name or by integer + index in the order in which they were stored. A typical + attribute would typically be parameters that describe the grid + or the data like, "origin" which would be the 3-vector of floats + which locates of the origin of a grid in 3-space. The method + used to write these attributes is writeAttribute();<p> + <b>C++ Prototype</b><br> + <code> + IEEEIO::writeAttribute(char *name,IObase::DataType numbertype,int length,void *data) + </code><p> + <DL> + <DT><i>name</i>: + <DD>Name of the attribute (like "origin" or "coordinates") + <DT><i>numbertype</i>: + <DD>The type of the data array associated with the attribute + <i>(<a href="DataTypes.html">datatype definition</a>)</i> + <DT><i>length</i>: + <DD>The number of elements in the data array. + <DT><i>data</i>: + <DD>The attribute data. + </DL><p> + So to write an attribute named <i>origin</i> along with a 3-vector float for the coordinates of the origin, you would use; + <pre> + float origin[3]={5.1,0.3,0.5}; + // and assuming the file is already open for writing + // the following attribute will be attached to the last + // written dataset. (you must have write data before adding attribs) + writer->writeAttribute("origin",IObase::Float32,3,origin); + </pre> + + <hr> + <a name="ReadAttribs"><h2>Reading Attributes</h2></a> + The attributes can be retrieved in the order they were written + or they can be retrieved by their name. To retrieve the + attributes in order, you would utilize the <b>nAttributes()</b> + method to determine how many attributes are attached, + <b>readAttributeInfo()</b> to get the size and type of the + attribute, and <b>readAttribute()</b> to read the attribute + data.<p> + <b>C++ Prototype</b><br> + <code>int IEEEIO::nAttributes()</code><p> + <DL> + <DT><i>returnvalue</i>: + <DD>Number of attributes in the file + </DL><p> + <b>C++ Prototype</b><br> + <code>IEEEIO::readAttributeInfo(int index,char *name,IObase::DataType &numbertype,int &length,int maxnamelength=128); + </code> + <DL> + <DT><i>index</i>: + <DD>The index of the attribute which can be 0 to (nattributes-1) + <DT><i>name</i>: + <DD>A buffer in which the name of the attribute will be placed. + <DT><i>numbertype</i>: + <DD>The type of the attribute data + <i>(<a href="DataTypes.html">datatype definition</a>)</i> + <DT><i>length</i>: + <DD>The number of elements in the attribute data. + <DT><i>maxnamelength</i>:<DD>The maximum size of a name that can be stored in the <b>name</b> buffer. The default maximum is 128, but can be set to any size. + </DL> +<p> + <b>C++ Prototype</b><br> + <code>IEEEIO::readAttribute(int index,void *data);</code> + <DL> + <DT><i>index</i>: + <DD>The index of the attribute data to read + <DT><i>data</i>: + <DD>The array into which the attribute data is copied. + </DL> + So for example, to read the attributes in order, you can use + <pre> + for(int i=0;i<infile->nAttributes();i++){ + char name[128]; + int length; + IObase::DataType datatype; + ... + infile->readAttributeInfo(i,name,datatype,length); + ... // allocate some data for storage + infile->readAttribute(i,data); + } + </pre><p> + + The attributes can also be retrieve by name. In fact, + the is the most likely way you will use the attibutes interface. + The readAttributeInfo() method is overloaded to allow retrieval + by name as well. It returns the index of the attribute if one + is found with a matching name: it returns -1 if one is not + found. + <p><b>C++ Prototype</b><br> + <code> + int IEEEIO::readAttributeInfo(char *name,IObase::DataType &numbertype,int &length); + </code> + <DL> + <DT><i>returnvalue</i>: + <DD>The index of the attribute if found or -1 if no attribute with matching name is found. + <DT><i>name</i>: + <DD>The name of the attribute to find. + <DT><i>numbertype</i>: + <DD>Returns the numbertype of the stored attribute data + <i>(<a href="DataTypes.html">datatype definition</a>)</i> + <DT><i>length</i>: + <DD>he length of the stored attribute data. + </DL> + So a typical use of this interface would be to find an attribute named "origin" and retrieve its data if it exists. + <pre> + int index = infile->readAttributeInfo("origin",datatype,length); + if(index>=0) // the attribute exists + infile->readAttribute(index,data); + else + puts("The attribute origin could not be found"); + </pre> + + </pre> + + <hr> + <a name="WriteAnn"><h2>Writing Annotations</h2></a> + An annotation is a text string which can be used to + describe a dataset. To write an annotation, you use the + writeAnnotation() method.<p> + <b>C++ Prototype</b><br> + <code> + IEEEIO::writeAnnotation(char *annotationtext) + </code> + <DL> + <DT><i>annotationtext</i>: + <DD>A null terminated string of the annotation text + </DL> + The annotation will be attached to the last written dataset. + You can store more than one annotation per dataset and the + annotations can be of arbitrary length.<p> + + <hr> + <a name="ReadAnn"><h2>Reading Annotations</h2></a> + The annotations are stored in the order they are written. The + method <b>nAnnotations()</b> is used to find out how many + attributes are attached to a dataset. The method + <b>readAnnotationInfo()</b> is used to find the length of the + annotation and <b>readAnnotatin()</b> reads the actual + annotation text.<p> + <b>C++ Prototype</b><br> + <code> + int nAnnotations(); + </code> + <DL> + <DT><i>returnvalue</i>: + <DD>Number of annotations attached to current dataset. + </DL><p> + <b>C++ Prototype</b><br><code> + readAnnotationInfo(int index,int &length) + </code> + <DL> + <DT><i>index</i>: + <DD>Index of the annotations which can be 0 to (nannotations-1) + <DT><i>length</i>: + <DD>Length in characters of the annotation. This includes the null-terminating character. + </DL> + <hr> + <a name="ReadWriteChunk"><h2>Writing and Reading in Chunks</h2></a> + For distributed-memory programming paradigms like HPF, MPI, or + PVM, it is often not unfeasible to write data to disk in a + single operation. For this reason, a <i>chunking</i> interface + is provided which allows you to write data in blocks to the + disk.<p> + To begin a chunk writing operation, you must first reserve a + data chunk in the file. This is accomplished using <b>reserveChunk()</b> + <b>C++ Prototype</b><br> + <code>IObase::reserveChunk(IObase::DataType datatype,int rank,int *dims); + </code><p> + Once space has been allocated in the datafile, you can write + blocks of data specified by their dimensions and origin using + <b>writeChunk()</b> + <b>C++ Prototype</b><br> + <code> + int IObase::IOwriteChunk(int *dims,int *origin,void *data); + </code><p> + Likewise, it is possible to read chunks from the disk as + well. No special procedure is required to select a record to + read in chunks. Simply use <a href="#Reading">readInfo()</a> + to get the dimensions and + type of the dataset and then use <b>readChunk()</b> in place + of <b>read()</b> in order to read-in the data. + <b>C++ Prototype</b><br> + <code> + int IObase::readChunk(int *dims,int *origin,void *data); + </code><p> + <hr> + <address><a href="mailto:jshalf@suttung.aei-potsdam.mpg.de">John Shalf</a></address> + <!-- Created: Mon Apr 7 12:52:52 MDT 1997 --> + <!-- hhmts start --> +Last modified: Thu Feb 4 21:53:13 CST 1999 +<!-- hhmts end --> + </body> +</html> |