Бьерн Страуструп - Язык программирования С++. Главы 8-10 - Файлы и потоки

ОГЛАВЛЕНИЕ

10.5 Файлы и потоки

Ниже приведена программа копирования одного файла в другой. Имена файлов берутся из командной строки программы:
     #include <fstream.h>
     #include <libc.h>

     void error(char* s, char* s2 ="")
     {
        cerr << s << ' ' << s2 << '\n';
        exit(1);
     }

     int main(int argc, char* argv[])
     {
         if (argc != 3) error("wrong number of arguments");

         ifstream from(argv[1]);
         if (!from) error("cannot open input file",argv[1]);

         ostream to(argv[2]);
         if (!to) error("cannot open output file",argv[2]);

         char ch;
         while (from.get(ch)) to.put(ch);

         if (!from.eof() || to.bad())
            error("something strange happened");

         return 0;
      }
Для открытия выходного файла создается объект класса ofstream - выходной поток файла, использующий в качестве аргумента имя файла. Аналогично, для открытия входного файла создается объект класса
ifstream - входной файловый поток, также использующий в качестве аргумента имя файла. В обоих случаях следуетпроверить состояние созданного объекта, чтобы убедиться в успешном открытии файла, а если это не так, операции завершатся не успешно, но корректно.

По умолчанию ifstream всегда открывается на чтение, а ofstream открывается на запись. В ostream и в istream можно использовать необязательный второй аргумент, указывающий иные режимы открытия:

     class ios {
     public:
         //...
         enum open_mode {
            in=1,            // открыть на чтение
            out=2,           // открыть как выходной
            ate=4,           // открыть и переместиться в конец файла
            app=010,         // добавить
            trunc=020,       // сократить файл до нулевой длины
            nocreate=040,    // неудача, если файл не существует
            noreplace=0100   // неудача, если файл существует
         };
         //...
     };
Настоящие значения для open_mode и их смысл вероятно будут зависеть от реализации. Будьте добры, за деталями обратитесь к руководству по вашей библиотеке или экспериментируйте. Приведенные комментарии могут прояснить их назначение. Например, можно открыть файл с условием, что операция открытия не выполнится, если файл уже не существует:
     void f()
     {
         ofstream mystream(name,ios::out|ios::nocreate);

         if (ofstream.bad()) {
             //...
         }
         //...
     }
Также можно открыть файл сразу на чтение и запись:
       fstream dictionary("concordance", ios::in|ios::out);
Все операции, допустимые для ostream и ostream, можно применять к fstream. На самом деле, класс fstream является производным от iostream, который является, в свою очередь, производным от istream и ostream.
Причина, по которой информация по буферизации и форматированию для ostream и istream находится в виртуальном базовом классе ios, в том, чтобы заставить действовать всю эту последовательность производных классов. По этой же причине операции позиционирования в istream и ostream имеют разные имена - seekp() и seekg(). В iostream есть отдельные позиции для чтения и записи.