View Single Post
Old Jan 10th, 2007, 2:36 PM   #9
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
You might want to consider some alternate methods.

SOME WAYS TO OPEN AND USE A FILE

Methods for opening files for reading and writing might be classified as C++, C stream, and C low-level methods. There are numerous variations, particularly with C++ streams; this post can in no way be considered exhaustive. CHECK YOUR DOCUMENTATION.

A NOTE ABOUT MODE

Unix/Linux have only one mode for file operations: binary. Windows has a text mode which is, unfortunately, the default. In text mode, content beyond what you supply is written to the file; it is stripped when you read the file. This makes the use of
random access (seek, tell, etc.), problematic. Even worse, a 'soft' EOF, a special character, is written. This indicator is NOT MOVED if you do an append, so appended data is not reachable unless you reset the EOF indication. Consequently, I recommend always using binary mode. With 'fopen,' you can specify a read or write or other mode as "rb", "wb", etc. Unix/Linux will accept and ignore the 'b', so you can use it portably. You can also set the default mode in Windows with the global variable, _fmode.

C++ USING FSTREAM

VC++ 6.0, Windows XP
Include iostream, fstream, and string for the following examples.

FSTREAM
OPENING FOR WRITE
   // Example variables
   string sFileName = "test.txt";
   string sContents = "File data\n";
   string sToken;
   char   lineBuffer [256];
   int    nCount = 0;

   // Construct an fstream object and attempt to open
   // for output
   fstream ooFile;
   ooFile.open (sFileName.c_str (), ios::binary | ios::out);

   // Test for success
   if (!ooFile.is_open ()) return badHappenstance ("Couldn't open file for writing");

   // Write example
   ooFile << sContents;

   // Test the write for success
   if (!ooFile.good ()) return badHappenstance ("Write failed");

   // Close the file.  Note that the file will be closed automatically when
   // the object is destroyed (goes out of scope).
   ooFile.close ();

OPENING FOR READ
   // Open it for input
   ooFile.open (sFileName.c_str (), ios::binary | ios::in);
   if (!ooFile.is_open ()) return badHappenstance ("Couldn't open file for reading");

   // Read tokens until end of file or error
   while (ooFile.good ())
   {
      ooFile >> sToken;
      cout << "Token " << ++nCount << ": ";
      if (sToken.size ()) cout << sToken; else cout << "(null token)";
      cout << endl;
   }
   // Check some status for grins
   if (ooFile.eof ()) cout << "Reached EOF" << endl;
   else if (ooFile.fail ()) return badHappenstance ("Read failed for some reason");

   // Alternatively, read entire line
   ooFile.getline (lineBuffer, sizeof (lineBuffer));

   // Always the status
   if (!(ooFile.good () || ooFile.eof ()))
      return badHappenstance ("Failure reading line");

   cout << "This is the line: " << lineBuffer << endl;

A SEEK EXAMPLE
   // Position to beginning after clearing EOF or fail bits
   ooFile.clear ();
   ooFile.seekg (0, ios::beg);
   if (!ooFile.good ()) return badHappenstance ("Seek failed");

   ooFile.close ();

Example output:
Quote:
Token 1: File
Token 2: data
Token 3: (null token)
Reached EOF
This is the line: File data
C USING FOPEN

Include stdio.h for this method.

OPENING FOR WRITE
   // Example variables
   FILE *ooFile;
   char  sFileName [] = "test.txt";
   char  sContents [] = "File data\n";
   char  sToken [32];
   char  lineBuffer [256];
   int   nCount = 0;
   int   status;

   // Attempt to open file for output
   ooFile = fopen (sFileName, "wb");

   // Test for success
   if (!ooFile) return badHappenstance ("Couldn't open file for writing");

   // Write the contents
   status = fputs (sContents, ooFile);

   // Test for success
   if (status == EOF) return badHappenstance ("Write failed");

   // Close the file
   fclose (ooFile);

OPENING FOR INPUT
   ooFile = fopen (sFileName, "rb");
   if (!ooFile) return badHappenstance ("Couldn't open file for reading");

   // Read tokens until end of file or error -- one method: fscanf
   // fscanf consumes whitespace, unlike some C++ methods
   // so there won't be a null token at the end.
   while (1)
   {
      if (fscanf (ooFile, "%s", sToken) != 1)
      {
         if (feof (ooFile)) 
         {
            printf ("Reached EOF\n");
            break;
         }
         else return badHappenstance ("Failed to read token");
      }
      printf ("Token %d: %s\n", ++nCount, sToken);
   }
// REPOSITIONING EXAMPLE

   rewind (ooFile);

   // Read a line all in one swell foop
   // We'll either fill the buffer or have a newline
   // at the end of the buffer, or both.  If you don't
   // want the newline:
   //
   //    index = strlen (lineBuffer) - 1;
   //    if (lineBuffer [index] == '\n')
   //        lineBuffer [index] = '\0';"
   //
   if (fgets (lineBuffer, sizeof (lineBuffer), ooFile) == NULL)
      // Always the status; EOF is okay, error is not
      if (ferror (ooFile)) return badHappenstance ("Failed to read line");

   printf ("This is the line: %s", lineBuffer);
   fclose (ooFile);

Example output:
Quote:
Token 1: File
Token 2: data
Reached EOF
This is the line: File data
C USING LOW LEVEL _open

As far as I'm concerned, low level file operations are only good for reading large amounts of binary data, and are not necessary for that. One is far better off using the higher level functions.

VC++ 6.0, Windows XP
Include stdio.h, io.h, fcntl.h, sys\stat.h, ctype.h, and string.h for the following example.

OPENING FOR READ/WRITE
typedef int fileHandle;
extern int errno;

   // Example variables
   fileHandle ooFile;
   char  sFileName [] = "test.txt";
   char  sContents [] = "File data\n";
   char  sToken [32];
   char  sTrash [32];
   char  lineBuffer [256];
   int   nChars, nTokens;
   int   status;

   // Attempt to open file for input/output
   ooFile = _open ("test.txt", _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY, _S_IWRITE);

   // Test for success
   if (ooFile == EOF) return badHappenstance (strerror (errno));

WRITING
   // Write the contents
   status = _write (ooFile, sContents, strlen (sContents));

   // Test for success
   if (status == EOF) return badHappenstance ("Write failed");

SEEK AND READ OPERATION -- Far more complex than higher level methods
   // Return to the beginning for input
   if (_lseek (ooFile, 0, SEEK_SET) == -1L)
      return badHappenstance ("Seek to beginning failed");

   // Read tokens until end of file or error
   nTokens = 0;
   while (1)
   {
      // Skip any whitespace
      while (status = _read (ooFile, sTrash, 1) == 1)
         if (!isspace (sTrash [0])) break;
      // Check for EOF or failure
      if (status < 0) return badHappenstance ("Failure to read data");
      else if (status == 0) break;
      sToken [0] = sTrash [0];
      for (nChars = 1; nChars < sizeof (sToken) - 1; nChars++)
      {
         status = _read (ooFile, &sToken [nChars], 1);
         // Check for EOF or failure
         if (status < 0) return badHappenstance ("Failure in reading data");
         else if ((status == 0) || (isspace (sToken [nChars])))
         {
            sToken [nChars] = '\0';
            break;
         }
      }
      // The token could be too long...
      if (nChars >= sizeof (sToken) - 1)
      {
         sTrash [0] = ' ';
         // Skip any remaining non-whitespace characters
         while (status = _read (ooFile, sTrash, 1) == 1)
            if (!isspace (sTrash [0])) break;
         // Check for EOF or failure
         if (status < 0) return badHappenstance ("Failure in reading data");
         else if (status == 0) break;
      }
      // Or we could have completed the token
      if (strlen (sToken) > 0) printf ("Token %d: %s\n", ++nTokens, sToken);
   }
   printf ("End of file\n");

   // Reposition to beginning
   if (_lseek (ooFile, 0, SEEK_SET) == -1L)
      return badHappenstance ("Seek to beginning failed");

   // Read one buffer's worth
   status = _read (ooFile, lineBuffer, sizeof (lineBuffer) - 1);
   if (status > 0) 
      lineBuffer [status] = '\0';

   printf ("This is the line: %s", lineBuffer);
   _close (ooFile);

   return 0;
}

Example output:
Quote:
Token 1: File
Token 2: data
End of file
This is the line: File data
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote