6.1.2. Reading and Writing

The CFile Class - MFC

2025-10-31

Written by: Jeff Prosise

A file opened with read access can be read using CFile::Read. A file opened with write access can be written with CFile::Write. The following example allocates a 4-KB file I/O buffer and reads the file 4 KB at a time. Error checking is omitted for clarity.

BYTE buffer[0x1000];
CFile file (_T ("File.txt"), CFile::modeRead);
DWORD dwBytesRemaining = file.GetLength ();
while (dwBytesRemaining) {
    UINT nBytesRead = file.Read (buffer, sizeof (buffer));
    dwBytesRemaining -= nBytesRead;
}

A count of bytes remaining to be read is maintained in dwBytesRemaining, which is initialized with the file size returned by CFile::GetLength. After each call to Read, the number of bytes read from the file (nBytesRead) is subtracted from dwBytesRemaining. The while loop executes until dwBytesRemaining reaches 0. The following example builds on the code in the previous paragraph by using ::CharLowerBuff to convert all the uppercase characters read from the file to lowercase and using CFile::Write to write the converted text back to the file. Once again, error checking is omitted for clarity.

BYTE buffer[0x1000];
CFile file (_T ("File.txt"), CFile::modeReadWrite);
DWORD dwBytesRemaining = file.GetLength ();
while (dwBytesRemaining) {
    DWORD dwPosition = file.GetPosition ();
    UINT nBytesRead = file.Read (buffer, sizeof (buffer));
    ::CharLowerBuff ((LPTSTR)buffer, nBytesRead);
    file.Seek (dwPosition, CFile::begin);
    file.Write (buffer, nBytesRead);
    dwBytesRemaining -= nBytesRead;
}

This example uses the CFile functions GetPosition and Seek to manipulate the file pointer—the offset into the file at which the next read or write is performed—so that the modified data is written over the top of the original. Seek’s second parameter specifies whether the byte offset passed in the first parameter is relative to the beginning of the file (CFile::begin), the end ofthe file (CFile::end), or the current position (CFile::current). To quickly seek to the beginning or end of a file, use CFile::SeekToBegin or CFile::SeekToEnd. Read, Write, and other CFile functions throw a CFileException if an error occurs during a file I/O operation. CFileException::m_cause tells you why the error occurred. For example, attempting to write to a disk that is full throws a CFileException with m_cause equal to CFileException::diskFull. Attempting to read beyond the end of a file throws a CFileException with m_cause equal to CFileException::endOfFile. Here’s how the routine that converts all the lowercase text in a file to uppercase might look with error checking code included:

BYTE buffer[0x1000];
try {
    CFile file (_T ("File.txt"), CFile::modeReadWrite);
    DWORD dwBytesRemaining = file.GetLength ();
    while (dwBytesRemaining) {
        DWORD dwPosition = file.GetPosition ();
        UINT nBytesRead = file.Read (buffer, sizeof (buffer));
        ::CharLowerBuff ((LPTSTR)buffer, nBytesRead);
        file.Seek (dwPosition, CFile::begin);
        file.Write (buffer, nBytesRead);
        dwBytesRemaining -= nBytesRead;
    }
}
catch (CFileException* e) {
    e->ReportError ();
    e->Delete ();
}

If you don’t catch exceptions thrown by CFile member functions, MFC will catch them for you. MFC’s default handler for unprocessed exceptions uses ReportError to display a descriptive error message. Normally, however, it’s in your best interest to catch file I/O exceptions to prevent critical sections of code from being skipped.

Ref