В данной статье рассказывается как открывать и закрывать файлы, а так
же как считывать и записывать в них данные. Класс CFile
обеспечивает основные бинарные оперции с файлами. Классы
CStdioFile, CMemFile наследованы от CFile и
используются для более специфической работы с файлами.
В MFC процесс открытия файла состоит из двух этапов.
Для открытия файла
- Сперва необходимо создать объект файла без указания пути или флагов
доступа (чтение, запись и т.д.).
Обычно объект файла создаётся путём объявления переменной типа
CFile.
- Далее необходимо вызвать метод Open для этого объекта, указав
путь и флаги доступа.
Если файл был открыт успешно, то функция Open вернёт ненулевое
значение, иначе, в случае ошибки будет возвращен 0 (ноль). Прототип
функции Open выглядит следующим образом: virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags,
CFileException* pError = NULL );
В параметре nOpenFlags передаются флаги доступа для файла, такие как
"только чтение" (read-only) и т.д. Возможные значения флагов определены
в виде констант в классе CFile, и использовать их можно с
приставкой "CFile::" - например CFile::modeRead. Для
создания файла используется флаг CFile::modeCreate.
Следующий пример показывает, как создать новый файл с правами на
чтение/запись (существующий файл с таким же путём будет заменён): char* pszFileName = "c:\\test\\myfile.dat";
CFile myFile;
CFileException fileException;
if ( !myFile.Open( pszFileName, CFile::modeCreate |
CFile::modeReadWrite, &fileException ) )
{
TRACE( "Can't open file %s, error = %u\n",
pszFileName, fileException.m_cause );
}
Заметка: Данный пример создаёт и открывает файл.
Если возникает какая-либо ошибка, то вызов Open может вернуть
объект CFileException в своём последнем параметре. Макрос
TRACE распечатывает как имя файла, так и код, указывающий на
причину ошибки. Если необходимо узнать более подробно о возникшей
ошибке, то можно воспользоваться функцией
AfxThrowFileException.
Теперь давайте посмотрим, как напрямую считывать и записывать в объект
CFile (для буфферизованного ввода/вывода используется класс CArchive ).
Чтобы прочитать и записать данные в файл
- Используются методы Read и Write соответственно. А так
же, для перемещения указателя внутри файла используется метод
Seek.
Read имеет два параметра (первый, это указатель на буфер, а
второй, это количество байт, которые необходимо считать) и возвращает
количество байт, которые были реально считаны. Например, если был
достигнут конец файла (end-of-file (EOF)), то функция вернёт количество
байт, оставшихся до конца файла. Если при чтении из файла произойдёт
ошибка, то возникнет исключительная ситуация. Write очень похожа на
Read, за исключением того, что не возвращает количество записанных
байт. Так же при возникновении ошибки произойдёт исключение. Следующий
пример показывает, как читать и записывать в объект CFile: char szBuffer[256];
UINT nActual = 0;
CFile myFile;
myFile.Write( szBuffer, sizeof( szBuffer ) );
myFile.Seek( 0, CFile::begin );
nActual = myFile.Read( szBuffer, sizeof( szBuffer ) );
Заметка: Исключительные ситуации при операциях
чтения/записи обрабатываются при помощи блока try/catch.
Более подробно см. Обработка исключений (MFC).
Когда работа с файлом завершена, необходимо закрыть его.
Чтобы закрыть файл
- Используется метод Close. Эта функция закрывает файл и, в
случае необходимости, сбрасывает в него буфер.
Если Вы создали объект CFile в классе или функции, то
объект будет автоматически закрыт и уничтожен как только выполнение кода
выйдет за пределы видимости объекта. Обратите внимание на то, что удаление
объекта CFile не приведёт к физическому удалению файла с диска.
CFile так же позволяет получить довольно обширную информацию о
файлах, включая существование файла, дату и время создания и изменения,
размер и путь.
Чтобы узнать, существует ли файл
- Воспользуйтесь статическим методом GetStatus.
GetStatus вернёт 0 если файл не существует.
Таким образом, можно использовать результат функции GetStatus,
чтобы определить, нужно ли использовать флаг CFile::modeCreate при
открытии файла. Следующий пример демонстрирует это: CFile theFile;
char* szFileName = "c:\\test\\myfile.dat";
BOOL bOpenOK;
CFileStatus status;
if( CFile::GetStatus( szFileName, status ) )
{
// Открываем файл не создавая его
bOpenOK = theFile.Open( szFileName,
CFile::modeWrite );
}
else
{
// Создаём файл и открываем его
bOpenOK = theFile.Open( szFileName,
CFile::modeCreate | CFile::modeWrite );
}
|