►Знакомство с подклассами fstream...278

We use cookies. Read the Privacy and Cookie Policy

Подклассы ofstream, ifstream и fstream объявлены в заголовочном файле fstream.h и обеспечивают потоки ввода-вывода в дисковые файлы. Эти три класса предоставляют множество функций для управления вводом и выводом, многие из которых наследуются от ostream и istream. Полный список этих функций вы можете найти в документации к компилятору, а здесь я приведу только несколько из них, чтобы вы могли с чего-то начать. 

_________________

278 стр. Часть 5. Полезные особенности

Класс ofstream, который используется для файлового вывода, имеет несколько конструкторов; наиболее часто применяется следующий:

    ofstream::ofstream( char* pFileName ,

                       int mode = ios::out ,

                       int prot = filebuff::openprot ) ;

Первый аргумент этого конструктора — указатель на имя открываемого файла. Второй и третий аргументы определяют, как именно должен быть открыт файл. Корректные значения аргумента mode приведены в табл. 24.2, a prot — в табл. 24.3. Эти значения являются битовыми полями, к которым применяется оператор побитового ИЛИ ( классы ios и filebuff — родительские по отношению к ostream ).

«Выражение ios::out представляет статический член-данные класса ios

[Советы]

    Таблица 24.2. Значения аргумента mode в конструкторе класса ofstream

    _________________

    Флаг — Назначение

    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

    ios::app — Дописывать в конец файла. Вернуть ошибку, если файл не существует

    ios::ate — Дописывать в конец файла, если он существует

    ios::in — Открыть файл для ввода ( подразумевается для istream )

    ios::out — Открыть файл для вывода ( подразумевается для ostream )

    ios::trunc — Обрезать файл до нулевой длины, если он существует ( используется по умолчанию )

    ios::nocreate — Если файла не существует, вернуть сообщение об ошибке

    ios::noreplace — Если файл существует, вернуть сообщение об ошибке

    ios::binary — Открыть файл в бинарном режиме ( альтернатива текстовому режиму )

    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

    Таблица 24.3. Значения аргумента prot в конструкторе класса ofstream

    _________________

    Флаг — Назначение

    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

    filebuf::openprot — Режим совместного чтения и записи

    filebuf::sh_none — Исключительный режим без совместного доступа

    filebuf::sh_read — Режим совместного чтения

    filebuf::sh_write — Режим совместной записи

   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Приведённая ниже программа открывает файл MyName.txt, а затем записывает в него некоторую важную информацию.

    /* StreamOutput — простой вывод в файл */

    #include <fstream>

    using namespace std ;

    int main( int nNumberofArgs , char* pszArgs[ ] )

    {

      setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */

        ofstream my( "MyName.txt" ) ;

        my << "С++ для чайников — очень хорошая книга"

           << endl ;

        system( "PAUSE" ) ; return 0 ;

    }

_________________ 

279 стр. Глава 24. Использование потоков ввода-вывода

Конструктор ofstream::ofstream( char* ) получает только имя, а потому использует для режима открытия файла значения по умолчанию. Если файл MyName.txt уже существует, он урезается; в противном случае создаётся новый файл MyName.txt. Кроме того, файл открывается в режиме совместного чтения и записи.

Второй конструктор, ofstream::ofstream( char* , int ), позволяет программисту указывать другие режимы ввода-вывода. Например, если бы я захотел открыть файл в бинарном режиме и произвести запись в конец этого файла ( если он уже существует ), я мог бы создать объект класса ofstream так, как это показано ниже ( напомню, что в бинарном режиме при выводе не выполняется преобразование символа новой строки в пару символов перевода каретки и новой строки , так же как при вводе не происходит обратного преобразования ).

    void fn( )

    {

        /* Откроем бинарный файл BINFILE для записи; если он  существует, дописываем информацию в конец файла */

        ofstream bfile( "BINFILE", ios::binary | ios::ate ) ;

        /* ...продолжение программы... */

    }

Потоковые объекты хранят информацию о состоянии процесса ввода-вывода. Функция-член bad( ) возвращает TRUE, если при работе с файловым объектом произошло что-то "плохое". Сюда входят такие неприятности, как невозможность открыть файл, нарушение внутренней структуры и т.п. Функция fail( ) указывает, что либо произошла ошибка, либо последнее чтение было неудачным. Функция good( ) возвращает TRUE, если и bad( ), и fail( ) возвращают FALSE. Функция clear( ) используется для сброса флага ошибки. Вот как выглядит добавление простейшей обработки ошибок к рассмотренной нами программе.

    /* StreamOutputWithErrorChecking —  простой вывод в файл */

    #include <fstream>

    #include <iostream>

    using namespace std ;

    int main( int nNumberofArgs , char* pszArgs[ ] )

    {

      setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */

        const static char fileName[ ] = "MyName.txt" ;

        ofstream my( fileName ) ;

        if ( my.bad( ) ) /* Открыть не удалось... */

        {

            cerr << "Ошибка открытия файла "

                  << fileName

                  << endl ;

            return 0 ; /* ...вывод сообщения и завершение работы */

        }

        my << "С++ для чайников — очень хорошая книга"

           << endl ;

        if ( my.bad( ) )

        {

            cerr << "Ошибка записи в файл "

                  << fileName

                  << endl ;

        }

        system( "PAUSE" ) ; return 0 ;

    }

_________________

280 стр. Часть 5. Полезные особенности

«Все попытки обратиться к объекту класса ofstream, который содержит ошибку, не вызовут никакого действия, пока флаг ошибки не будет сброшен с помощью функции clear( )

[Советы]

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

Класс ifstream работает для ввода почти так же, как ofstream для вывода, что и демонстрирует приведённый ниже пример.

    /* StreamInput — ВВОД ДАННЫХ С ИСПОЛЬЗОВАНИЕМ fstream */

    #include <fstream>

    #include <cstdlib>

    #include <iostream>

    using namespace std ;

    ifstream* openFile( )

    {

        ifstream* pFileStream = 0 ;

        for ( ; ; )

        {

            /* Открытие файла, указанного пользователем */

            char fileName[ 80 ] ;

            cout << "Введите имя файла с целыми числами"

                 << endl ;

            cin >> fileName ;

            /* Открываем файл для чтения; не создавать файл, если его не существует */

            pFileStream = new ifstream( fileName ) ;

            if ( pFileStream -> good( ) )

            {

                break ;

            }

            cerr << "Невозможно открыть " << fileName << endl ;

            delete pFileStream ;

        }

        return pFileStream ;

    }

    int main( int nNumberofArgs , char* pszArgs[ ] )

    {

      setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */

        /* Получение файлового потока */

        ifstream* pFileStream = openFile( ) ;

        /* Остановиться по достижению конца файла */

        while ( !pFileStream -> eof( ) )

        {

            /* Чтение значения */

            int nValue = 0 ;

            ( *pFileStream ) >> nValue ;

            /* Останов при ошибке чтения ( например, считывается не целое число, или считан символ новой строки, после которого ничего нет */

            if ( pFileStream -> fail( ) )

            {

                break ;

            }

            /* Вывод считанного значения */

            cout << nValue << endl ;

        }

        delete pFileStream ;

        system( "PAUSE" ) ; return 0 ;

    }

_________________ 

281 стр. Глава 24. Использование потоков ввода-вывода

Функция openFile( ) запрашивает у пользователя имя открываемого файла и создаёт поток с этим именем. Создание объекта ifstream автоматически открывает файл для ввода. Если файл открыт корректно, функция возвращает указатель на объект ifstream, который используется для чтения. В противном случае объект удаляется и повторяется попытка открыть файл. Единственный способ выйти из цикла — ввести правильное имя файла или завершить выполнение программы.

«Не забывайте о необходимости удаления pFileStream, если вы не смогли открыть файл. Это позволит избежать утечек памяти.»

[Советы]

Программа считывает целые числа до тех пор, пока не дойдёт до конца файла ( проверяется при помощи функции-члена eof( ) ) или не произойдёт ошибки чтения ( функция fail( ) ). Попытка прочитать информацию с помощью объекта класса ifstream с установленным флагом ошибки приведёт к немедленному возврату без считывания данных. Для сброса флага ошибки используйте функцию clear( ).

«Ещё раз напомню, что при чтении из потока в состоянии ошибки ничего считано не будет. Более того, буфер останется неизменным, так что программа может прийти к ошибочному выводу, что прочитано такое же значение, как и перед этим. Кстати, при наличии ошибки функция eof( ) никогда не вернёт true

[Советы]

Вывод этой программы имеет следующий вид.

    Введите имя файла с целыми числами

    testfile

    Невозможно открыть testfile

    Введите имя файла с целыми числами

    integers.txt

    123

    456

    234

    654

    4363

    48923

    78237

    Press any key to continue...