Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КЛ_ТехнолПрогр2010_090103.doc
Скачиваний:
22
Добавлен:
27.04.2019
Размер:
1.35 Mб
Скачать

2.5 Средства управления файлами

Операции и средства обработки файлов

Язык C++ не имеет встроенных в язык средств файлового ввода/вывода. Для этого используются библиотеки ввода/вывода. Настоятельно рекомендуем пользоваться базовой библиотекой потокового ввода/вывода iostream C++, как наиболее гибкой и элегантной по сравнению с другими библиотеками, например, с stdio.

Потоком называется абстрактное понятие, относящееся к переносу данных от источника к приемнику. Имя потока используется в операциях записи и чтения файла. Файл - это поименованная совокупность данных, хранящаяся на внешнем носителе.

Основными этапами обработки файлов являются:

- открытие потока;

- связывание потока с файлом;

- запись и чтение данных файла;

- закрытие файла.

Существуют предопределенные потоки, для которых не нужны операции открытия потока и связывания его с файлом: cin - стандартный поток ввода данных (файл - клавиатура); cout - стандартный поток вывода данных(файл -экран дисплея); cerr- стандартный поток вывода ошибок; буферизируется поблочно, очистка буфера производится при каждой новой вставке; clog - полностью буферизированная версия cerr.

Для использования средств управления файлами базовой библиотеки потокового ввода/вывода необходимо включить в программу два файла заголовков: #include <iostream.h> и #include <fstream.h>.

Открытие потока заключается в объявлении идентификатора потока и по умолчанию режима открытия (ввод, вывод,ввод и вывод).

- Синтаксис оператора открытия потока:

ifstream p; //открытие потока p на чтение (ввод)

ofstream p; //открытие потока p на запись (вывод)

fstream p; //открытие потока p на чтение и запись

Связывание потока с файлом заключается в назначении открытому ранее потоку конкретного файла на диске, а также в возможности установления дополнительных режимов потока.

- Синтаксис оператора связывания:

p.open(imfile[,<режим 1>|<режим 2>...]); ,где p - имя открытого ранее потока, imfile - имя файла на диске, <режим1>- символическая константа режима открытия файла. Символические константы режимов открытия файла следующие:

ios::in - открытие файла на чтение (ввод);

ios::out - открытие файла на запись (вывод);

ios::app - добавление данных в конец файла;

ios::ate - перемотка к концу файла;

ios::trunc - сжатие файла до нуля (очистка содержимого);

ios::nocreate - если файл не существует, то ошибка;

ios::noreplace - если файл существует, то ошибка;

ios::binary - открытие в двоичном режиме (по умолчанию -

текстовый).

Пример:

ofstrem f1; //первый этап - открытие потока f1

f1.open ("karta.dat", ios::app|ios::binary); //второй этап

Открытый ранее поток f1 связывается с файлом "karta.dat" и открывается на добавление данных в конец файла в двоичном режиме.

Раздельное выполнение операций открытия и связывания позво­ляет открывать поток только один раз и связывать этот поток с различными файлами.

Операции открытия и связывания можно выполнять одновременно.

- Синтаксис оператора открытия и связывания потока:

ifstream p(imfile[,<режим 1>|<режим 2>...]);

ofstream p(imfile[,<режим 1>|<режим 2>...]);

fstream p(imfile[,<режим 1>|<режим 2>...]);

Пример:

ofstrem f1("karta.dat",ios::app|ios::binary);

Выбор средств для операций чтения/записи определяется видом хранимых данных файла:

- Файлы с непрерывной последовательностью символов используют для записи символа в файл операцию вставки(<<) или функцию put , для чтения символа - операцию извлечения(>>) или функцию get.

Примеры:

p<<ch;//запись символа, p-имя потока, ch-переменная типа char

p.put(ch); //альтернатива операции <<

p>>ch; //чтение символа

p.get(ch); //get с параметром ch=p.get();//get без параметра

- Файлы из строк символов переменной длины используют для записи строки в файл операцию << или функцию write, для чтения строки - операцию >> или функции read или get-строка.

Примеры:

p<<str;//запись строки, str - переменная типа массив char

p.write(str,n);//альтернатива <<, n- кол-во записыв. символов

p>>str; //чтение строки до разделителя (пробел,'\n')

p.get(str,n); //альтернатива >>, n- кол-во читаемых символов

p.read(str,n);

- Файлы из форматированных данных разного типа с разделителями (пробелами) могут использовать для записи и чтения данных операции << и >>, при этом происходят преобразования данных.

- Файлы из записей фиксированной длины состоят из компонент типа структура и могут использовать для записи и чтения целой структуры функции write и read.

- Синтаксис операции записи:

p.write((char *)&zap,sizeof(zap)); ,где p - идентификатор потока, zap - переменная типа струк­тура, & - операция адресации, sizeof(zap) - размер переменной zap в байтах.

- Синтаксис операции чтения:

p.read((char *)&zap,sizeof(zap));

- Синтаксис оператора закрытия файла:

p.close( );//закрывается файл,связанный потоком p.

Для организации прямого доступа к записям файла используются функции seekg и seekp.

- Синтаксис функций установки указателей чтения и записи файла на n байт от точки отсчета:

p.seekg((long)n, <точка отсчета>); //указатель чтения

p.seekp((long)n,<точка отсчета>);//указатель записи

Точки отсчета следующие: ios::beg - начало файла, ios::end - конец файла, ios::cur - текущая позиция указателя.

-Синтаксис функций определения текущей позиции указателей:

streampos m=p.tellg; //m - позиция указателя чтения

streampos m=p.tellp; //m - позиция указателя записи ,где streampos -тип,определенный в библиотеке с помощью typedef, как тип long.

Контроль операций обработки файлов

Контроль операций обработки файлов заключается в проверке состояния потока (обнаружение ошибок) и ,если возможно, восстановление потока (очистка ошибок). Рассмотрим средства, проверяющие операции открытия файла, чтения и записи.

Состояние потока оценивается битами класса ios:

goodbit - устанавливается, если операция прошла успешно;

eofbit - устанавливается, если больше нет символов для чтения, т.е. конец файла;

failbit - устанавливается, если операция чтения/записи закончилась с ошибкой; поток можно использовать после сброса бита;

badbit - устанавливается, если операция чтения/записи закончилась ошибкой; возможна потеря символов, но можно попробовать исправить, сбросив бит;

hardbit - устанавливается при неисправимой ошибке.

Восстановление потока,т.е. очистка битов ошибки, осуществля­ется функцией clear:

p.clear(n); , где n - либо код бита (0,1,2,4,8), либо его мнемоническое обозначение; при n=0 происходит очистка всех битов ошибок.

Состояние потока можно проверить различными способами. Проверка состояния потока с обнаружением конкретной ошибки выполняется функцией rdstate, которая возвращает код бита ошибки. Пример:

switch(p.rdstate()) //p - поток

{

case ios::goodbit: //операция успешна,продолжение программы

break;

case ios::eofbit: //конец файла, продолжение программы

break;

case ios::failbit: //ошибка, восстановление потока

break;

case ios::badbit: //ошибка, попытка восстановления потока

break;

case ios::hardbit: //неисправимая ошибка, выход из программы

break;

}

Альтернативным, вторым способом проверки состояния потока яв­ляется использование функций класса ios:

good() - возвращает истину, если установлен goodbit (нет ошибок); возвращает ложь(ноль),если бит не установлен;

eof() - возвращает истину, если установлен eofbit (конец файла); возвращает ложь,если бит не установлен;

fail() - возвращает истину, если установлен failbit,badbit или hardbit; возвращает ложь,если биты не установлены;

bad() - возвращает истину, если установлен badbit или hard­bit; возвращает ложь,если биты не установлены.

Примеры:

if (!p.good()) if (p.fail()) while(!p.eof())

{ { {

cerr<<"Ошибка..."; cerr<<"Ошибка..."; //нет конца файла

exit(-1); //выход exit(-1);//выход ...

} } }

Удобен третий способ проверки состояния потока представлени­ем имени потока или операции чтения/записи в виде логического вы­ражения в операторах if, for, while, do-while.

Примеры :

if (p) if (!p)

{ {

//продолжение программы cerr<<"Ошибка...";

... exit(-1);//выход

} }

if (p.read((char*)&z,sizeof(z))) if(!p.read((char*)&z,sizeof(z)))

{ {

//продолжение программы cerr<<"Ошибка чтения...";

... exit(-1);//выход из программы

} }

Имя потока p и операция чтения p.read имеют значение не ноль (истинно), если нет ошибки, и ноль (ложно), если есть ошибка.

Контрольные вопросы

  1. Какие имеются способы обозначения комментариев?

  2. Что такое директива препроцессора?

  3. Что такое управляющая последовательность?

  4. Что такое массив?

  5. Что такое указатель?

  6. Чем отличаются ссылки от указателей?

  7. Что такое структура?

  8. Что такое перечисление?

  9. Что такое операции извлечения (>>) и вставки (<<)?

  10. Какие имеются способы форматирования ввода/вывода?

  11. Какие средства обработки файлов имеет библиотека потокого ввода/вывода fstream.h?