It is currently Mon Apr 24, 2017 12:28 am

All times are UTC - 5 hours




 Page 1 of 1 [ 4 posts ] 
Author Message
 Post subject: Custom File Handling
PostPosted: Fri Jan 27, 2012 5:59 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
Im trying to create a struct that handles the opening, reading, writing and closing of a file with easy for both text and binary. Once I get this structure working correctly, I will add in the ability to append. At the moment I am working with FILE*. Later I will add in the ability to use fstream as well by calling an overloaded open() func. Here is what I have so far.

core.h
#ifndef _CORE_H
#define _CORE_H

#include "stdafx.h"

// Constant Globals For Stack Size, And Max Array Elements
// Filename Helpers
const int EXTENSION_LENGTH  =    4;
const int FILENAME_LENGTH   =  257;

// File Handling Definitions
#define READ  0
#define WRITE 1
#define BIN   0
#define TXT   1

// Usefull Enumerations
enum FileOpen {
   READ_FROM_FILE,
   WRITE_TO_FILE,
};

enum FileType {
   BINARY_FILE,
   TEXT_FILE,
};

struct File {
   char   _szFilename[FILENAME_LENGTH];
   FILE*   _fp;
   
   inline File() {      
      memset( _szFilename, 0, FILENAME_LENGTH );
      _fp = NULL;
   } // File

   ~File() {
      close();      
   } // ~File

   inline FILE* open( const char* szFilename, int iReadWrite = WRITE, int iBinTxt = TXT );
   inline void  close();
private:
   FILE* (File::*ReadWrite)(void);
   inline FILE* ReadBinary(void);
   inline FILE* WriteBinary(void);
   inline FILE* ReadText(void);
   inline FILE* WriteText(void);
}; // File

// -----------------------------------------------------------------------
// open()
// Opens A File With Name Passed In, And Determines Read/Write And Bin/Txt
// Based On User Selection, By Default It Is Set To Write Txt
// This Function For This Structure Allows The User To Easily
// Read And Write To A Bin And Or Txt Version Of Their File Type.
inline FILE* File::open( const char* szFilename, int iReadWrite, int iBinTxt ) {
   // Copy Over Filename Even If It Is NULL
   sprintf_s( _szFilename, FILENAME_LENGTH-1, "%s", szFilename );
      
   // If Our Member Is NULL We Return And Destroy Object
   if ( _szFilename == NULL ) {
      _fp = NULL;
   }

   // Clamp Our Values
   if ( iReadWrite <= READ ) {
      iReadWrite = READ;
   } else {
      iReadWrite = WRITE;
   }

   if ( iBinTxt <= BIN ) {
      iBinTxt = BIN;
   } else {
      iBinTxt = TXT;
   }

   // Determine What User Wants To Do
   switch ( iBinTxt ) {
      case BINARY_FILE: {
         if ( iReadWrite == READ_FROM_FILE ) {
            ReadWrite = &File::ReadBinary;            
            break;
         }
         if ( iReadWrite == WRITE_TO_FILE ) {            
            ReadWrite = &File::WriteBinary;            
            break;
         }
      }
      case TEXT_FILE: {      
         if ( iReadWrite == READ_FROM_FILE ) {
            ReadWrite = &File::ReadText;            
            break;
         }
         if ( iReadWrite == WRITE_TO_FILE ) {
            ReadWrite = &File::WriteText;
            break;
         }
      }
   } // switch

   return _fp;

} // Open

// -----------------------------------------------------------------------
// close()
// Closes The Current File, Sets The Pointer To NULL And Sets The Filename To NULL
inline void File::close() {
   if ( _szFilename != NULL ) {
      if ( _fp != NULL ) {
         fclose( _fp );
         _fp = NULL;
         //printf( "File was closed (%s).\n", _szFilename );
         memset( _szFilename, 0, FILENAME_LENGTH );         
      }
      else {
         memset( _szFilename, 0, FILENAME_LENGTH );
      }
   } else {
      _fp = NULL;
   }
} // close

// -----------------------------------------------------------------------
// ReadBinary()
//
inline FILE* File::ReadBinary() {   
   fopen_s( &_fp, _szFilename, "rb" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not read from (%s)", _szFilename );
   }
   return this->_fp;
} // ReadBinary

// -----------------------------------------------------------------------
// WriteBinary()
//
inline FILE* File::WriteBinary() {   
   fopen_s( &_fp, _szFilename, "wb" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not write to (%s)", _szFilename );
   }
   return this->_fp;   
} // WriteBinary

// -----------------------------------------------------------------------
// ReadText()
//
inline FILE* File::ReadText() {
   fopen_s( &_fp, _szFilename, "rt" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not read from (%s)", _szFilename );
   }
   return this->_fp;   
} // ReadText

// -----------------------------------------------------------------------
// WriteText()
//
inline FILE* File::WriteText() {
   fopen_s( &_fp, _szFilename, "wt" );
   if( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not write to (%s)", _szFilename );
   }
   return this->_fp;
} // WriteText

#endif _CORE_H

core.cpp only contains #include "stdafx.h" & #include "core.h"

main.cpp
#include "stdafx.h"
#include "Core.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{   
   const char* szFile1 = "files\\test1.bin";
   const char* szFile2 = "files\\test1.txt";
   char  cName[8] = "Francis";

   File* file = NULL;
   file = new File();
   if ( !file ) {
      return -1;
   } else {
      file->open( szFile1, 1, 0 );
      fwrite( cName, sizeof(char), 8, file->_fp );
      file->close();
   }

   delete file;

   return 0;
}


For some reason when fwrite is being called I am getting an error, I can not seem to figure out why. Any help on pointing out any and all errors would be great, and any place to improve the code too. Thanks ahead of time.


Offline
 Profile  
 
 Post subject: Re: C++ VMK 11 - File Handling
PostPosted: Sat Jan 28, 2012 6:47 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
Have a look at the fopen function
http://www.cplusplus.com/reference/clib ... dio/fopen/


Offline
 Profile  
 
 Post subject: Re: C++ VMK 11 - File Handling
PostPosted: Sun Jan 29, 2012 5:59 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I changed my code from above to this, and so far it seems to work for writing to a new file and reading from an existing one.

core.h
#ifndef _CORE_H
#define _CORE_H

#include "stdafx.h"

// Constant Globals For Stack Size, And Max Array Elements
// Filename Helpers
const int EXTENSION_LENGTH  =    4;
const int FILENAME_LENGTH   =  257;

// File Handling Definitions
#define READ  0
#define WRITE 1
#define BIN   0
#define TXT   1

// Usefull Enumerations
enum FileOpen {
   READ_FROM_FILE,
   WRITE_TO_FILE,
};

enum FileType {
   BINARY_FILE,
   TEXT_FILE,
};

struct File {
   char   _szFilename[FILENAME_LENGTH];
   FILE*   _fp;
   
   inline File( const char* szFilename, int iReadWrite = WRITE, int iBinText = TXT ) {
      
      memset( _szFilename, 0, FILENAME_LENGTH );
      // Copy Over Filename Even If It Is NULL
      sprintf_s( _szFilename, FILENAME_LENGTH-1, "%s", szFilename );
      
      // If Our Member Is NULL We Return And Destroy Object
      if ( _szFilename == NULL ) {
         _fp = NULL;
      }

      _fp = open( iReadWrite, iBinText );

   } // File

   ~File() {
      close();      
   } // ~File   

private:
   inline FILE* open( int iReadWrite, int iBinTxt );
   inline void  close();

   inline FILE* ReadBinary();
   inline FILE* WriteBinary();
   inline FILE* ReadText();
   inline FILE* WriteText();

}; // File

// -----------------------------------------------------------------------
// open()
// Opens A File And Determines Read/Write And Bin/Txt Based On User Selection
inline FILE* File::open( int iReadWrite, int iBinTxt ) {

   // Clamp Our Values
   if ( iReadWrite <= READ ) {
      iReadWrite = READ;
   } else {
      iReadWrite = WRITE;
   }

   if ( iBinTxt <= BIN ) {
      iBinTxt = BIN;
   } else {
      iBinTxt = TXT;
   }

   // Determine What User Wants To Do
   switch ( iBinTxt ) {
      case BINARY_FILE: {
         if ( iReadWrite == READ_FROM_FILE ) {
            _fp = ReadBinary();            
            break;
         }
         if ( iReadWrite == WRITE_TO_FILE ) {            
            _fp = WriteBinary();            
            break;
         }
      }
      case TEXT_FILE: {
      
         if ( iReadWrite == READ_FROM_FILE ) {
            _fp = ReadText();            
            break;
         }
         if ( iReadWrite == WRITE_TO_FILE ) {
            _fp = WriteText();
            break;
         }
      }
   } // switch

   return _fp;

} // Open

// -----------------------------------------------------------------------
// close()
// Closes The Current File, Sets The Pointer To NULL And Sets The Filename To NULL
inline void File::close() {
   if ( _szFilename != NULL ) {
      if ( _fp != NULL ) {
         fclose( _fp );
         _fp = NULL;
         //printf( "File was closed (%s).\n", _szFilename );
         memset( _szFilename, 0, FILENAME_LENGTH );         
      }
      else {
         memset( _szFilename, 0, FILENAME_LENGTH );
      }
   } else {
      _fp = NULL;
   }
} // close

// -----------------------------------------------------------------------
// ReadBinary()
//
inline FILE* File::ReadBinary() {
   
   fopen_s( &_fp, _szFilename, "rb" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not read from (%s)", _szFilename );
   }
   return this->_fp;

} // ReadBinary

// -----------------------------------------------------------------------
// WriteBinary()
//
inline FILE* File::WriteBinary() {
   
   fopen_s( &_fp, _szFilename, "wb" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not write to (%s)", _szFilename );
   }
   return this->_fp;
   
} // WriteBinary

// -----------------------------------------------------------------------
// ReadText()
//
inline FILE* File::ReadText() {

   fopen_s( &_fp, _szFilename, "rt" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not read from (%s)", _szFilename );
   }
   return this->_fp;
   
} // ReadText

// -----------------------------------------------------------------------
// WriteText()
//
inline FILE* File::WriteText() {

   fopen_s( &_fp, _szFilename, "wt" );
   if( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not write to (%s)", _szFilename );
   }
   return this->_fp;

} // WriteText

#endif _CORE_H


main.cpp
#include "stdafx.h"
#include "Core.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
   
   const char* szFile1 = "files\\test1.bin";
   const char* szFile2 = "files\\test1.txt";
   char  cName[] = "Francis";

   File* file1 = NULL;
   File* file2 = NULL;
   
   file1 = new File( szFile1, 1, 0 );
   if ( !file1 ) {
      return -1;
   } else {
      fwrite( cName, 1, sizeof(cName), file1->_fp );
      //file->close();
   }
   delete file1;

   file2 = new File( szFile2, 1, 1 );
   if ( !file2 ) {
      return -1;
   } else {
      fwrite( cName, 1, sizeof(cName), file2->_fp );
   }
   delete file2;

   char* szData = NULL;
   long lSize = 0;

   file1 = new File( szFile1, 0, 0 );
   if ( !file1 ) {
      return -1;
   } else {
      fseek( file1->_fp, 0, SEEK_END );
      lSize = ftell( file1->_fp );
      rewind( file1->_fp );

      szData = new char[sizeof(char*)*lSize+1];
      fread( szData, 1, lSize, file1->_fp );
   }

   printf( "%s\n", szData );
   delete file1;


   return 0;
}


This is a very nice structure. I will be adding the ability to append in the future. I may also include the string options with the "+" in them for file manipulation.


Offline
 Profile  
 
 Post subject: Re: C++ VMK 11 - File Handling
PostPosted: Sun Jan 29, 2012 9:22 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I added the ability to append to a file, I did change some things in the structure too. I moved the open and close functions back into the public section of the structure instead of private. I originally had the idea for the constructor to automatically open and close the file, but when I was working in the main.cpp file I needed access to the close() function to close the file when I was done with writing or reading from it, then needed access to the open() function to reopen the same file but for a different type of modification. Here is the modified structure.

core.h
#ifndef _CORE_H
#define _CORE_H

#include "stdafx.h"

// Constant Globals For Stack Size, And Max Array Elements
// Filename Helpers
const int EXTENSION_LENGTH  =    4;
const int FILENAME_LENGTH   =  257;

// File Handling Definitions
#define READ      0
#define WRITE     1
#define APPEND    2
#define BIN       0
#define TXT       1

// Usefull Enumerations
enum FileOpen {
   READ_FROM_FILE,
   WRITE_TO_FILE,
   APPEND_FILE,
};

enum FileType {
   BINARY_FILE,
   TEXT_FILE,
};

struct File {
   char   _szFilename[FILENAME_LENGTH];
   FILE*   _fp;
   
   inline File( const char* szFilename, int iRWA /*Read Write Append*/, int iBinText ) {
      _fp = open( szFilename, iRWA, iBinText );
   } // File

   ~File() {
      close();      
   } // ~File   

   inline FILE* open( const char* szFilename, int iRWA /*Read Write Append*/, int iBinTxt );
   inline void  close();
private:

   inline FILE* readBinary();
   inline FILE* writeBinary();
   inline FILE* appendBinary();
   inline FILE* readText();
   inline FILE* writeText();
   inline FILE* appendText();

}; // File

// -----------------------------------------------------------------------
// open()
// Opens A File And Determines Read/Write/Append And Bin/Txt Based On User Selection
inline FILE* File::open( const char* szFilename, int iRWA /*Read Write Append*/, int iBinTxt ) {

   memset( _szFilename, 0, FILENAME_LENGTH );
   // Copy Over Filename Even If It Is NULL
   sprintf_s( _szFilename, FILENAME_LENGTH-1, "%s", szFilename );
      
   // If Our Member Is NULL We Return And Destroy Object
   if ( _szFilename == NULL ) {
      _fp = NULL;
   }

   // Clamp Our Values
   if ( iRWA <= READ ) {
      iRWA = READ;
   } else if ( iRWA > WRITE ) {
      iRWA = APPEND;
   } else {
      iRWA = WRITE;
   }

   if ( iBinTxt <= BIN ) {
      iBinTxt = BIN;
   } else {
      iBinTxt = TXT;
   }

   // Determine What User Wants To Do
   switch ( iBinTxt ) {
      case BINARY_FILE: {
         if ( iRWA == READ_FROM_FILE ) {
            _fp = readBinary();            
            break;
         }
         if ( iRWA == WRITE_TO_FILE ) {            
            _fp = writeBinary();            
            break;
         }
         if ( iRWA == APPEND_FILE ) {
            _fp = appendBinary();
            break;
         }
      }
      case TEXT_FILE: {
      
         if ( iRWA == READ_FROM_FILE ) {
            _fp = readText();            
            break;
         }
         if ( iRWA == WRITE_TO_FILE ) {
            _fp = writeText();
            break;
         }
         if ( iRWA == APPEND_FILE ) {
            _fp = appendText();
            break;
         }
      }
   } // switch

   return _fp;

} // Open

// -----------------------------------------------------------------------
// close()
// Closes The Current File, Sets The Pointer To NULL And Sets The Filename To NULL
inline void File::close() {
   if ( _szFilename != NULL ) {
      if ( _fp != NULL ) {
         fclose( _fp );
         _fp = NULL;
         //printf( "File was closed (%s).\n", _szFilename );
         memset( _szFilename, 0, FILENAME_LENGTH );         
      }
      else {
         memset( _szFilename, 0, FILENAME_LENGTH );
      }
   } else {
      _fp = NULL;
   }
} // close

// -----------------------------------------------------------------------
// readBinary()
//
inline FILE* File::readBinary() {
   
   fopen_s( &_fp, _szFilename, "rb" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not read from (%s)", _szFilename );
   }
   return this->_fp;

} // readBinary

// -----------------------------------------------------------------------
// writeBinary()
//
inline FILE* File::writeBinary() {
   
   fopen_s( &_fp, _szFilename, "wb" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not write to (%s)", _szFilename );
   }
   return this->_fp;
   
} // writeBinary

// -----------------------------------------------------------------------
// appendBinary()
//
inline FILE* File::appendBinary() {

   fopen_s( &_fp, _szFilename, "ab" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not append to (%s)", _szFilename );
   }
   return this->_fp;

} // appenedBinary

// -----------------------------------------------------------------------
// readText()
//
inline FILE* File::readText() {

   fopen_s( &_fp, _szFilename, "rt" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not read from (%s)", _szFilename );
   }
   return this->_fp;
   
} // readText

// -----------------------------------------------------------------------
// writeText()
//
inline FILE* File::writeText() {

   fopen_s( &_fp, _szFilename, "wt" );
   if( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not write to (%s)", _szFilename );
   }
   return this->_fp;

} // writeText

// -----------------------------------------------------------------------
// appendText()
//
inline FILE* File::appendText() {

   fopen_s( &_fp, _szFilename, "at" );
   if ( !_fp ) {
      memset( _szFilename, 0, FILENAME_LENGTH );
      this->_fp = NULL;
      printf( "Can not append to (%s)", _szFilename );
   }
   return this->_fp;

} // appenedText

#endif // _CORE_H


main.cpp
#include "stdafx.h"
#include "Core.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
   
   const char* szFile1 = "files\\test1.txt";
   char  cName[] = "Francis";
   char  cLast[] = "Cugler";

   File file1( szFile1, WRITE, TXT );
   fwrite( cName, 1, sizeof(cName), file1._fp );
   file1.close();

   char* szData = NULL;
   long lSize = 0;

   file1.open( szFile1, READ, TXT );
   fseek( file1._fp, 0, SEEK_END );
   lSize = ftell( file1._fp );
   rewind( file1._fp );
   szData = new char[sizeof(char*)*lSize+1];
   fread( szData, 1, lSize, file1._fp );
   file1.close();
   
   printf( "%s\n", szData );

   file1.open( szFile1, APPEND, TXT );
   fwrite( cLast, 1, sizeof(cLast), file1._fp );

   return 0;
}


I also removed the default values in the constructor and open() function, the use must specify the values.


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 4 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Jump to:  

cron