HEC-DSS can store and retrieve virtually any file by storing files as binary objects. For Windows, when such a file is retrieved from HEC-DSS, the function "system" can be executed to cause the default Windows function to be run on that file, based on the file's extension, just as if the user had double clicked on it in Windows Explorer. For example, if the extension is .pdf, Adobe Reader would be run, displaying the file. If .xls or .xlsx, Microsoft Excel would start with that file loaded (assuming Excel was installed.) If it were .mp3, Windows Media Player would start playing the file.

Storing files in HEC-DSS is available in both versions 6 and 7.

The pathname conventions for File data are:

Parts A, B and F – not specified
Part C: The file name
Part E: The file's extension (without the "." Separator)

For an image file (e.g., .jpg), use the following conventions:
     Part D: "IMAGE"
     Data type: DATA_TYPE_IMAGE (600)

For all other files, use:
     Part D: "FILE"
     Data type: DATA_TYPE_FILE (610)

To store and retrieve binary objects (files and all other data), the fundamental zread and zwrite functions are used along with a zStructTransfer struct. The minimum items needed for storing using zStructTransfer are:

  • The pathname
  • The data, in values1
  • The number of int values in values1Number
  • The data type

For example:

zStructTransfer *transferStruct = zstructTransferNew("/a/b/myDoc.pdf/FILE/pdf/f/", 0);
transferStruct->dataType = DATA_TYPE_FILE;
transferStruct->values1 = (int *)buffer; // Read in ealier
transferStruct->values1Number = ((bufferSize - 1) / 4) + 1; // storing ints
status = zwrite(ifltab, transferStruct);

To retrieve a binary object, use function zread and zstructTransferNew with a mode of "1", which allocates space in the transfer struct for the data (otherwise, you need to pre-allocate it.):

zStructTransfer *transferStruct = zstructTransferNew("/a/b/myDoc.pdf/FILE/pdf/f/", 1);
status = zread(ifltab, transferStruct);

The following functions are used with binary objects:

zStructTransfer* zstructTransferNew(const char* pathname, int mode)
int zwrite(long long ifltab, zStructTransfer ztransfer)
int zread(long long ifltab, zStructTransfer ztransfer)

Where mode in zstructTransferNew is a flag assigned to all array modes. Generally, set mode to 0 for storing, mode to 1 for reading:

mode == 0, no memory will be allocated for the array. Do not read this array.
mode == 1, whatever memory is needed will be allocated
mode > 1, this is the memory allocated for the array. Will not access memory > mode.

The Java HEC interface has several additional tools for handling images and files. Refer to the HEC-DSS Java documentation for more information.

BLOBs (Binary Large Objects)

You can use the same functions to store essentially anything else that has not been defined by the HEC-DSS conventions. At this level, the pathname is just a string of characters, null terminated. The pathname can be whatever length desired, does not have to use "/" delimiters, but must contain only printable ASCII characters.

You can store whatever data is desired in any of the six data areas in the zStructTransfer, and identify the size of each data area in ints. Set the data type to 0 (undefined).

However, if you have undefined binary data, functions in utility programs, such as DSSVue, will not be able to display, show or work with it.

(Note, binary files may not be compatible when transferring between little endian (PCs) and big endian (Solaris) machines, unless the correct swapping functions are used.)

Example: Image Example – saving and displaying a .jpg file


#include <stdio.h>
#include "heclib.h"

//  Reads a jpg file, stores in DSS, reads back in,
//  and then displays with system viewer
int ExampleFiles1()
{
         long long ifltab[250];
         FILE *input;
         FILE *output;
         char *buffer;
         size_t fileSize;
         size_t sizeRead;
         zStructTransfer *trans1, *trans2;
         int status;
         char *myPictureFile;
         int bufferSize;

         //  Put the name of your jpg here!
         myPictureFile = mallocAndCopy("C:/temp/Images/houston2016.jpg");

         //  Open the DSS file; Create if it doesn't exist
         status = zopen(ifltab, "C:/temp/Example7.dss");
         //  If an error occured, messages will be printed to standard out
         if (status != STATUS_OKAY) return status;

         input = fopen(myPictureFile, "rb");
         if (!input) {|
                 printf("Could not open input file %s!\n", myPictureFile);
                 return -1;
         }

         //  Quick way to get file size
         fseek(input, 0, SEEK_END); // seek to end of file
         fileSize = ftell(input); // get current file pointer
         fseek(input, 0, SEEK_SET); // go back to the beginning

         buffer = (char *)malloc(fileSize+4);
         if (!buffer) {
                 printf("Error allocating memory\n");
                 return -1;
         }

         //  Read file 
         sizeRead = fread(buffer, sizeof(char), fileSize, input);
         if (sizeRead != fileSize) {
                 perror("Error reading file\n");
                 return -1;
         }

         fclose(input);

         //  Write to DSS
         trans1 = zstructTransferNew("/a/b/myPicture.jpg/IMAGE/jpg/f/", 0);
         trans1->dataType = DATA_TYPE_IMAGE;  // 610;  So other programs (e.g., DSSVue know how to handle)
         trans1->values1 = (int *)buffer;
         trans1->values1Number = ((fileSize - 1) / 4) + 1;  //  storing ints

         status = zwrite(ifltab, trans1);
         if (status != STATUS_OKAY) {
                 printf("Error during zwrite\n");
                 return status;
         }

free(buffer);
         buffer = 0;
         zstructFree(trans1);
         free(myPictureFile);

         //  Read in and write to a file
         trans2 = zstructTransferNew("/a/b/myPicture.jpg/IMAGE/jpg/f/", 1);
         status = zread(ifltab, trans2);
         if (status != STATUS_OKAY) {
                 printf("Error during zread\n");
                 return status;
         }

         output = fopen("C:/temp/myPicture.jpg", "wb");
         if (!output) {
                 perror("Could not open output file!\n");
                 return -1;
         }
         status = fwrite(trans2->values1, sizeof(int), trans2->values1Number, output);
         if (status < 1) {
                 perror("Error writing file\n");
                 return -1;
         }
         fclose(output);

         zstructFree(trans2);
         zclose(ifltab);


         //  Now tell the system to run the default with that file.
         system("C:\\temp\\myPicture.jpg");
         return 0;
}
CODE


Example: File Example – saving and playing an .mp3 file


#include <stdio.h>
#include "heclib.h"

//  Similar to example files 1, but does mp3
//  Reads a mp3 file, stores in DSS, reads back in,
//  and then plays with system music player
int ExampleFiles2()
{
         long long ifltab[250];
         FILE *input;
         FILE *output;
         char *buffer;
         size_t fileSize;
         size_t sizeRead;
         zStructTransfer *trans1, *trans2;
         int status;
         char *myMusicFile;

         //  Put the name of your mp3 here!
         myMusicFile = mallocAndCopy("C:/temp/Carry_On.mp3");

         //  Open the DSS file; Create if it doesn't exist
         status = zopen(ifltab, "C:/temp/Example7.dss");
         //  If an error occured, messages will be printed to standard out
         if (status != STATUS_OKAY) return status;

         //  Put
         input = fopen(myMusicFile, "rb");
         if (!input) {
                 printf("Could not open input file %s!\n", myMusicFile);
                 return -1;
         }

         //  Quick way to get file size
         fseek(input, 0, SEEK_END); // seek to end of file
         fileSize = ftell(input); // get current file pointer
         fseek(input, 0, SEEK_SET); // go back to the beginning

         buffer = (char *)malloc(fileSize+4);
         if (!buffer) {
                 printf("Error allocating memory\n");
                 return -1;
         }

         //  Read file 
         sizeRead = fread(buffer, sizeof(char), fileSize, input);
         if (sizeRead != fileSize) {
                 perror("Error reading file\n");
                 return -1;
         }

         fclose(input);
         free(myMusicFile);

         //  Write to DSS
         trans1 = zstructTransferNew("/a/b/myMusic.mp3/FILE/mp3/f/", 0);
         trans1->dataType = DATA_TYPE_FILE;   // 600.  So other programs (e.g., DSSVue) know how to handle
         trans1->values1 = (int *)buffer;
         trans1->values1Number = ((fileSize - 1) / 4) + 1;  //  storing ints
         status = zwrite(ifltab, trans1);
         if (status != STATUS_OKAY) {
                 printf("Error during zwrite\n");
                 return status;
         }

free(buffer);
         buffer = 0;
         zstructFree(trans1);

         //  Read in and write to a file
         trans2 = zstructTransferNew("/a/b/myMusic.mp3/FILE/mp3/f/", 1);
         status = zread(ifltab, trans2);
         if (status != STATUS_OKAY) {
                 printf("Error during zread\n");
                 return status;
         }

         output = fopen("C:/temp/myMusic.mp3", "wb");
         if (!output) {
                 perror("Could not open output file!\n");
                 return -1;
         }
         status = fwrite(trans2->values1, sizeof(int), trans2->values1Number, output);
         if (status < 1) {
                 perror("Error writing file\n");
                 return -1;
         }
         fclose(output);

         zstructFree(trans2);
         zclose(ifltab);

         //  Now tell the system to run the default with that file.
         system("C:\\temp\\myMusic.mp3");

         return 0;
}
CODE


zStructTransfer


#include "zStructAllocation.h"

//  This is primarily an internal struct
//
//  For reading:
//               Mode == 0:   Don't read this array.
//               Mode == 1:       Allocate space and read into new space.
//                                         Number will contain number allocated.
//               Mode >  1:       Space has already been allocated and this is
//                                         the maximum number ints available

typedef struct {

         //  Private
         int structType;

         char *pathname;
         int pathnameLength;
         int dataType;

         int *internalHeader;
         int internalHeaderNumber;
         int internalHeaderMode;

         int *header2;
         int header2Number;
         int header2Mode;

         int *userHeader;
         int userHeaderNumber;
         int userHeaderMode;

         int *values1;
         int values1Number;
         int values1Mode;

         int *values2;
         int values2Number;
         int values2Mode;

         int *values3;
         int values3Number;
         int values3Mode;

         int numberValues;
         int logicalNumberValues;
         int totalAllocatedSize;
         int totalExpandedSize;

         int version;
         int insufficientSpace;
         long long lastWrittenTime;
         long long fileLastWrittenTime;
         char programName[17];

         long long *info;

         char allocated[zSTRUCT_length];

} zStructTransfer;
CODE