📄 fileio.c
字号:
/* Contents: Functions related to file input and output. Author: Markus Hagenbuchner Comments and questions concerning this program package may be sent to 'markus@artificial-neural.net' ChangeLog: 24/10/2006 - Added support to read from gzip compressed files. *//************//* Includes *//************/#include <ctype.h>#include <limits.h>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <zlib.h>#include "common.h"#include "data.h"#include "fileio.h"#include "system.h"#include "utils.h"/**************************//* Locally used constants *//**************************//* Field names found in a datafile */#define MAXFIELDS 10 /* Maximum number of fields in a datafile */#define NODELABEL 1 /* Node label */#define CHILDSTATE 2 /* Network state for a nodes' offsprings */#define PARENTSTATE 3 /* Network state for the parents of a node */#define TARGET 4 /* Target vector of a node *///#define GRAPHNO 5 /* Number of graph to which this node belongs */#define NODENO 6 /* Number of a node in the graph */#define DEPTH 7 /* Depth of the node in a graph (leafs:depth=0) */#define LINKS 8 /* A node's (out-)link definitions */#define LABEL 9 /* A symbolic class label for the node */#define STATE 10 /* State of neighbors of a node (undirected gph) *//* Begin functions... *//******************************************************************************Description: Open a file stream named by fname, and initialize a FileInfo structure. This function has some support for compressed files. This is realized by 'abusing' the FILE pointer and setting the appropriate ctype flag.Return value: Pointer to a properly initialized FileInfo structure, or NULL if the file could not be opened.******************************************************************************/struct FileInfo* OpenFile(char *fname, char *mode){ struct FileInfo* fileinfo; FILE *fptr = NULL; int ctype = RAW; if (fname == NULL || mode == NULL) /* If no file name given */ return NULL; if (*mode == 'r') /* If to open in read mode, */ ctype = GetCompressStatus(fname, mode); /* check if file is compressed */ switch(ctype){ case RAW: /* It is an uncompressed file */ if ((fptr = fopen(fname, mode)) == NULL){/* try to open it */ AddError("Unable to open RAW file."); return NULL; } break; case GZIP: /* gzip compressed file */ if ((fptr = (FILE*)gzopen(fname, mode)) == NULL){/* try to open it */ AddError("Unable to open GZIP file."); return NULL; } break; case BZIP: AddError("Bzip2 compressed files not yet suppored by som-sd."); break; default: AddError("Unknown file type reported by function GetCompressStatus()."); } /* Store file info in structure */ fileinfo = (struct FileInfo*)MyCalloc(1, sizeof(struct FileInfo)); fileinfo->fname = fname; fileinfo->fptr = fptr; fileinfo->ctype = ctype; return fileinfo;}/******************************************************************************Description: Close a file stream and free memory used by the structure pointed to by finfo.Return value: This function does not return a value.******************************************************************************/void CloseFile(struct FileInfo *finfo){ if (finfo == NULL) /* If no data given */ return; /* then return immediately */ if (finfo->fptr){ /* If file is open and */ switch(finfo->ctype){ /* depending on whether or how it was compressed */ case RAW: fclose(finfo->fptr);/* close RAW file */ break; case GZIP: gzclose((gzFile)finfo->fptr);/* close gzip compressed file */ break; case BZIP: /* close bzip2 compressed file (if supported) */ break; default: /* all other file types are unsupported and ignored*/ break; } } free(finfo); /* Free up memory used by the structure */}/******************************************************************************Description: Similar to fgetc but can read a compressed stream depending on the ctype (compression type) of the file.Return value: An unsigned char cast to an int containing the next character read from stream, or EOF on end of file or error.******************************************************************************/inline int zgetc(struct FileInfo *finfo){ switch(finfo->ctype){ /* depending on whether or how it was compressed */ case RAW: return fgetc(finfo->fptr); /* read from RAW file, or */ case GZIP: return gzgetc((gzFile)finfo->fptr);/* read from gzip compressed file, or */ case BZIP: /* read from bzip2 compressed file (if supported) */ break; } return 0;}/******************************************************************************Description: Similar to fungetc but can push c back into a compressed stream depending on the ctype (compression type) of the file.Return value: c on success, or EOF on error.******************************************************************************/inline int zungetc(int c, struct FileInfo *finfo){ switch(finfo->ctype){ /* depending on whether or how it was compressed */ case RAW: return ungetc(c, finfo->fptr); /* push back into RAW file, or */ case GZIP: return gzungetc(c, (gzFile)finfo->fptr);/* back to gzip compressed file, */ case BZIP: /* or back into bzip2 compressed file (if supported) */ break; } return 0;}/******************************************************************************Description: An auxillary function which reads a value from a possibly compressed ASC-II data stream. This function was written since there is no fscanf equivalent in the zlib or bzlib library. Thus this function is to behaves similarly to fscanf but allows only at most one! format character which can be either f or d.Return value: An unsigned char cast to an int containing the next character read from stream, or EOF on end of file or error.******************************************************************************/int zscanf(struct FileInfo *finfo, const char *format, void *target){ switch(finfo->ctype){ /* depending on whether or how it was compressed */ case RAW: return fscanf(finfo->fptr, format, target); /* Read from RAW stream */ case GZIP:/* read from gzip compressed file, or */ { char buffer[256]; int c, pos = 0; for(pos = 0; ; pos++){ c = gzgetc((gzFile)finfo->fptr); if ((c == '-' && pos == 0) || isdigit(c) || c == '.') buffer[pos] = c; else{ gzungetc(c, (gzFile)finfo->fptr);/* back into gzip compressed file */ buffer[pos] = '\0'; break; } } return sscanf(buffer, format, target); /* Read from buffer */ } case BZIP: /* read from bzip2 compressed file (if supported) */ break; } return 0;}/******************************************************************************Description: Reads a line of text from a given input file stream. The text is stored in a dynamically allocated and zero terminated string. The newline character is read but not stored.Return value: Pointer to the next line of text read from the given file, or NULL if no data could be read.******************************************************************************/char *ReadLine(struct FileInfo *finfo){ static char *cptr = NULL; static unsigned clen = 0; unsigned count = 0; int cval; /* Clear buffer and return NULL pointer if no more data can be read */ if (finfo == NULL || finfo->fptr == NULL || (cval = zgetc(finfo)) == EOF){ free(cptr); cptr = NULL; clen = 0; return NULL; } finfo->lineno++; while(1){ if (clen <= count){ //Dynamically increase buffer size as needed clen = clen + 64; cptr = MyRealloc(cptr, clen); } if (cval == '\n' || cval < 0){ // At the end of line or end of file cptr[count] = '\0'; // close string and exit the loop break; } cptr[count++] = (char)cval; // Store character in buffer then cval = zgetc(finfo); // read next character from file } return cptr; // Return pointer to buffer}/******************************************************************************Description: Reads a text word from a given input file stream. The text is stored in a dynamically allocated and zero terminated string. Leading and trailing whitespaces as well as the newline character define word boundaries, are read but not stored in the word.Return value: Pointer to the text word read from the given file, or NULL if no data could be read.******************************************************************************/char *ReadWord(struct FileInfo *finfo){ char *cptr = NULL; unsigned clen = 0; unsigned count = 0; int cval; /* Return NULL pointer if no more data can be read */ if (finfo == NULL || finfo->fptr==NULL || (cval = zgetc(finfo)) == EOF) return NULL; while (cval != EOF && isspace(cval)){/* Find the first non-white space char*/ if (cval == '\n'){ /* End of line reached - no word left to read */ zungetc(cval, finfo); /* return the whitespace to the stream */ return NULL; /* return NULL */ } cval = zgetc(finfo); /* Get next character */ } if (cval < 0) /* End of file reached - no word there to read, return NULL */ return NULL; while(1){ if (clen <= count){ /* Dynamically increase buffer size as needed */ clen = clen + 4; /* Increase by boundary size (32bit) */ cptr = MyRealloc(cptr, clen); } if (isspace(cval)){ /* At whitespace or the end of line */ zungetc(cval,finfo); /* return the whitespace to the stream */ cptr[count] = '\0'; /* close string and exit the loop */ break; } else if (cval < 0){ /* At end of of file */ cptr[count] = '\0'; /* close string and exit the loop */ break; } cptr[count++] = (char)cval; /*Store character in buffer then */ cval = zgetc(finfo); /*read next character from file */ } return cptr; /* Return pointer to word */}/****************************************************************************Description: Like fread but considers the byte order and performs an appropriate convertion if necessary, and is able to read from a compressed stream.Return value: Same as fread (the number of bytes read)****************************************************************************/size_t bo_fread(void *ptr, size_t size, size_t nmemb, struct FileInfo *fi){ static int endian = 0; char *cptr, cval; size_t i,j; size_t res; FILE *fp = fi->fptr; if (!endian) endian = FindEndian(); //Fill the buffer switch(fi->ctype){ case RAW: res = fread(ptr, size, nmemb, fp); break; case GZIP: res = gzread((gzFile)fp, ptr, size*nmemb)/size; break; case BZIP: res = 0; break; default: res = 0; } /* Return immediately if the byteorder in file is the same as on machine, or if single bytes are to be read */ if (endian == fi->byteorder || size == 1) return res; if (size & 1 || size > 16){ //Odd-sized types or larger 128bit not supported. fprintf(stderr, "Internal error: Unsupported datatype in bo_fread\n"); exit(0); } //Do the actual byte swapping cptr = (char*)ptr; if ((endian == BIG_ENDIAN && fi->byteorder == LITTLE_ENDIAN) || (endian == LITTLE_ENDIAN && fi->byteorder == BIG_ENDIAN)){ //Converting between BIG_ENDIAN and LITTLE_ENDIAN means to mirror bytes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -