Шаг 494.
Библиотека STL.
Ввод-вывод с использованием потоковых классов. Пример доступа к файлам

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

    Следующая программа открывает файл charset.out и записывает в него текущий набор символов (все символы в интервале 32-255):

//---------------------------------------------------------------------------

#include <vcl.h>
#include <string>       // Строки
#include <iostream>     // Ввод-вывод
#include <fstream>      // Файловый ввод-вывод
#include <iomanip>      // setw()
#include <cstdlib>      // exit()

#include <conio.h>   //необходимо для getch()

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;

std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}

// Опережающие объявления
void writeCharsetToFile (const string& filename);
void outputFile (const string& filename);

int main (int argc, char* argv[])
{
  writeCharsetToFile("charset.out");
  outputFile("charset.out");
  cout << ToRus("Работа выполнена");
  getch();
  return 0;
}

void writeCharsetToFile (const string& filename)
{
  // Открытие выходного файла
  ofstream file(filename.c_str());

  // Файл открыт?
  if (! file) {
      // НЕТ, аварийное завершение программы
      cerr << ToRus("Не могу открыть файл \"") << filename << "\""
           << endl;
      exit(EXIT_FAILURE);
  }

  // Вывод текущего набора символов
  for (int i=32; i<256; i++) {
      file << ToRus("Значение: ") << setw(3) << i << "   "
           << ToRus("Символ:   ") << static_cast<char>(i) << endl;
  }

}   // Автоматическое закрытие файла

void outputFile (const string& filename)
{
  // open input file
  ifstream file(filename.c_str());

  // Файл открыт?
  if (! file) {
    // НЕТ, аварийное завершение программы
      cerr << ToRus("Не могу открыть файл \"") << filename << "\""
           << endl;
      exit(EXIT_FAILURE);
  }

  // Копирование содержимого файла в cout
  char c;
  while (file.get(c)) {
      cout.put(c);
  }

}   // Автоматическое закрытие файла


//---------------------------------------------------------------------------
Текст этого примера можно взять здесь.

    Результат работы приложения изображен на рисунке 1


Рис.1. Результат работы приложения

    В функции writeCharsetToFile() конструктор класса ofstream открывает файл с заданным именем:

  std::ofstream file(filename.c_str());

    Имя файла передается в типе string, поэтому его преобразование в const char* выполняется функцией c_str(). К сожалению, у классов файловых потоков данных не существует конструктора, вызываемого с аргументом типа string. После преобразования программа проверяет состояние потока данных:

  if (!file) {
    .   .   .   .
  }

    Если открыть поток данных не удалось, условие будет истинным. После проверки программа в цикле выводит числа от 32 до 255 вместе с соответствующими символами.

    Внутри функции outputFile() файл открывается конструктором класса ifstream, после чего происходит посимвольная запись нового содержимого файла.

    В конце обеих функций открытые файлы автоматически закрываются при выходе соответствующих потоков данных из области видимости. Деструкторы классов ifstream и ofstream закрывают файлы, если они остаются открытыми на момент уничтожения объекта.

    Если файл должен использоваться за пределами области видимости, в которой он был создан, выделите объект из кучи и удалите его позднее, когда надобность в нем отпадет:

  std::ofstream* filePtr = new std::ofstream("xyz"); 
  .   .   .   .   .
  delete filePtr;

    В таких случаях следует использовать классы умных указателей, например CountedPtr (смотри 190 шаг) или auto_ptr (смотри 59 шаг).

    Вместо последовательного вывода отдельных символов также можно вывести все содержимое файла одной командой, передавая указатель на потоковый буфер файла в аргументе оператора <<:

  std::cout << file.rdbuf();

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




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