Шаг 84.
Среда программирования Visual C++.
Класс CFile. Чтение и запись файла

    На этом шаге мы рассмотрим средства, используемые для чтения из файла и запись в файл.

    Для поддержки операций прямого небуферизованного чтения и записи в дисковые файлы в CFile существуют функции Read() и Write(), которые обращаются к ReadFile() и WriteFile() - стандартным функциям Microsoft Windows API. Поскольку прямой доступ к файлу - дело весьма непростое (например, буферы и смещения указателей надо задавать в единицах, кратных размеру сектора дискового тома), в библиотеке времени выполнения существуют функции потокового ввода/вывода (stream I/O).

    Они позволяют работать с любым форматом данных дисковых файлов: от отдельных символов до больших структур данных. Также эти функции поддерживают буферизацию ввода/вывода, что иногда позволяет улучшить быстродействие системы. Вот несколько членов этого семейства: fopen(), fseek(), fread() и fwrite(). Так как Вы программируете на C++, Вы наверняка знакомы с потоковым вводом/выводом с применением классов iostream.

    В MFC потоковый ввод/вывод обеспечивается классом CStdioFile. Его функции-члены Read() и Write() обращаются к библиотечным функциям потокового ввода/вывода. Всегда пользуйтесь гибким и простым в применении CStdioFile, кроме тех случаев, когда Вам требуется прямой низкоуровневый доступ к файлу.

    Файлы, связанные с объектом CStdioFile, открываются либо в текстовом, либо в двоичном режиме. В первом случае поддерживается специальная обработка пары символов "перевод каретки/перевод строки" (CR/LF). В этом режиме символ новой строки (0х0А), передаваемый объекту CStdioFile, записывается в файл как пара байт (0x0D, 0х0А), соответствующих CR/LF, а при считывании эта пара преобразуется обратно в один байт 0х0А. Чтобы открыть объект CStdioFile как текстовый файл, в функцию Ореn() нужно передать флаг CFile::typeText следующим образом:

   CStdioFile inFile("MyFile.txt",   CFile::modeRead  | CFile::typeText);

    Для задания двоичного режима служит флаг CFile::typeBinary. В этом случае символы новой строки никак не преобразуются.

    Для чтения данных из файлового объекта CStdioFile предназначены две функции: Read() и ReadString().

    В первую передается указатель на буфер, в который будут помещаться данные, полученные в процессе чтения, а также целое беззнаковое значение (типа UINT), задающее число байт, которые требуется считать. Read() возвращает число считанных байт. Если из-за доcтижения конца файла заданное число байт получить не удается, функция возвратит число реально считанных байт.

    Ошибка чтения заставляет CFileException возбудить исключение. При записи в текстовом режиме пользуйтесь функцией ReadString(), которая почти полностью идентична Read(). Отличие ее вот в чем:

    ReadString() позволяет считать отдельную строку текстового файла и возвращает булево значение, указывающее на успех или неудачу операции.

    Write() похожа на Read() тем, что также имеет два параметра: буфер с записываемой информацией и число байт, которые требуется записать. Но Write() не возвращает количество записанных байт. При сбое (им считается и невозможность записать все указанные байты) CFileException генерирует исключение. При записи в текстовом режиме пользуйтесь функцией CStdioFile::WriteString(), который позволяет вставлять символ новой строки.

    Приведенный ниже код иллюстрирует, как использовать класс CStdioFile для записи и чтения дисковых файлов. Программа открывает файл MyFiIe.bin в двоичном режиме и считывает его блоками по 10 байт. Каждый блок записывается в новой строке специально созданного файла Output.txt:

try
{
  CStdioFile inFile("MyFile.bin", CFile::modeRead | CFile::typeBinary); 
  CStdioFile outFile("outfile.txt", 
      CFile::modeCreate | CFile::modeWrite | CFile::typeText);
  const UINT linelength = 10; 
  TCHAR strBuf[16];
  while(inFile.ReadString(strBuf, linelength))
  {
    _tcscat(strBuf,  _T("\n")); 
    outFile.WriteString(strBuf);
  }
catch(CFileException * fx)
TCHAR buf[255];
fx->GetErrorMessage(buf, 255); 
AfxMessageBox(buf);
}

    На следующем шаге мы рассмотрим прямой доступ к файлу.




Предыдущий шаг Содержание Следующий шаг