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
|