|
Программирование >> Разработка устойчивых систем
Пример обработки файлов Следующий пример демонстрирует многие возможности, упоминавщиеся до настоящего момента. Обратите внимание на включение заголовка <fstream> с объявлениями классов файлового ввода-вывода. Хотя на многих платформах компилятор также автоматически включает заголовок <iostream>, он не обязан это делать. Чтобы программа была действительно переносимой, всегда включайте оба заголовка. : C04:Strf1le.cpp Потоковый ввод-вывод на примере файлов Демонстрация различий между get() и getlineO linclude <fstream> linclude <iostream> linclude ../require.h using namespace std: int mainO { const int sz - 100: Размер буфера char buf[sz]: { ifstream in( Strfile.cpp ): Чтение assureCin. Strfile.cpp ); Проверка успешного открытия ofstream out( Strfile.out ): Запись assure(out. Strfile.out ): int i - 1: Line counter Неудобный способ построчного ввода: while(in.get(buf. sz)) { \n остается в прочитанных данных in.getO: Отбросить следующий символ (\п) cout buf endl: Необходимо добавить \п Вывод в файл напоминает стандартный вывод: out i++ : buf endl: } Деструкторы закрывают файлы in и out ifstream in( Strfile.out ); assure(in, Strfile.out ): Более удобный способ построчного ввода: while(in.getline(buf. sz)) { Удаляет \n char* cp - buf: while(*cp !- :) cp++: cp +- 2; Пропустить : cout cp endl; Bee равно необходимо добавить \n } III:- Сразу же за созданием объектов ifstream и ofstream следуют вызовы assure(), которые проверяют, что файл был успешно открыт. В этом случае объект, использованный в контексте логического выражения, возвращает логический признак успеха или неудачи. Первый цикл while демонстрирует две формы функции get(). Первая форма читает символы в буфер и помещает в него нуль-символ либо по прочтении SZ-1 символов, либо при обнаружении завершителя, указанного в третьем аргументе (\п по умолчанию). Функция get() оставляет завершитель во входном потоке. поэтому его приходится отдельно удалять вызовом in.get() без аргументов, когда один байт читается и возвращается в виде int. Также можно воспользоваться функцией класса ignore(), имеющей два аргумента. В первом аргументе передается количество игнорируемых символов (по умолчанию 1). Второй аргумент определяет символ, при обнаружении (и после извлечения) которого функция ignore() завершает работу. По умолчанию этот символ равен EOF. Дальше идут две команды, внешне очень похожие: одна выводит данные в cout, а другая - в out. Такое сходство чрезвычайно удобно: вам не приходится беспокоиться о типе объекта, поскольку команды форматирования одинаково работают для всех объектов ostream. Первая команда дублирует строку в стандартном выходном потоке, а вторая записывает строку в новый файл с включением номера строки. Чтобы продемонстрировать работу функции getline(), мы открываем только что созданный файл и удаляем из него номера строк. Но как гарантировать, что файл будет должным образом закрыт перед его открытием для чтения? Есть два способа. Можно заключить первую часть программы в фигурные скобки; объект out выходит из области видимости, для него вызывается деструктор, и файл автоматически закрывается. Именно этот вариант использован в нашем примере. Кроме того, можно вызвать функцию close() для обоих файлов; это даже позволит заново использовать объект in вызовом функции ореп(). Второй цикл while показывает, как функция getline() удаляет символы-завершители (третий аргумент, по умолчанию \п) из входного потока. Хотя функция getline(), как и get(), заносит в буфер ноль, символ-завершитель в буфере не сохраняется. В этом примере, как и в большинстве примеров этой главы, предполагается, что каждый вызов перегруженной версии getline() находит символ перевода строки. Если это условие нарушается, для потока будет установлен флаг конца данных, и вызов getlineO вернет false; в результате программа потеряет последнюю строку входных данных. Режимы открытия файла Вы можете выбрать нужный режим открытия файлов, передавая конструктору нужное значение вместо аргументов по умолчанию. Далее перечислены флаги, управляющие режимом открытия файла. ios::in Открывает файл для чтения. Флаг используется при открытии ofstream для предотвращения усечения существующих файлов. i OS::out Открывает файл для записи. При использовании для ofstream без флагаios::app, ios::ate или ios::in, подразумевается ios::trunc. ios::арр Выходной файл открывается только для присоединения данных. los::ate Открывает существующий файл (для чтения или записи) и устанавливает текущую позицию в конец файла. Буферизация Одно из основных правил разработки гласит, что при создании нового класса необходимо по возможности скрыть подробности реализации от пользователя класса. Пользователь видит только то, что необходимо для его работы, а остальные члены класса объявляются закрытыми. Используя операторы и , вы обычно не знаете (да вам и не нужно знать), с чем именно вы работаете: с консолью, файлом, блоком памяти, каким-то новым классом или устройством. Но в какой-то момент возникает необходимость в том компоненте потока ввода-вывода, который непосредственно выдает или принимает ваты. Чтобы предоставить единый интерфейс к этому компоненту, в стандартной библиотеке он абстрагируется в отдельный класс streambuf. Любой объект потока содержит указатель на некоторый объект streambuf (конкретный тип зависит от того, с чем работает поток: с консолью, файлом, памятью и т. д.). С объектом streambuf можно ios::trunc Усекает содержимое существующих файлов. ios::binary Открывает файл в двоичном режиме. По умолчанию используется текстовый режим. Флаги объединяются поразрядным оператором . Флаг двоичного режима является переносимым, но влияет только на открытие файлов в некоторых системах, не входящих в семейство Unix, в частности, в клонах MS-DOS, в которых применяются особые правила хранения завершителей строк. Например, в системах MS-DOS в текстовом режиме (используемом по умолчанию) при каждой записи в поток символа перевода строки (\п) файловая система на самом деле выводит два физических символа с А5СП-кодами OxOD (CR, возврат курсора) и ОхОА (LF, перевод строки). Соответственно, при чтении такого файла в память в текстовом режиме каждое вхождение этой пары байтов заменяется символом \п, который передается программе. Чтобы предотвратить эту замену, откройте файл в двоичном режиме. Двоичный режим не имеет никакого отношения к возможности записи произвольных байтов в файл - такая возможность присутствует всегда (посредством вызова write()). Тем не менее, при использовании функций read() и write() следует открывать файлы именно в двоичном режиме, потому что в параметрах этим функциям передается количество байтов, которое будет искажено присутствием дополнительных символов. Если вы собираетесь задействовать команды позиционирования, описанные далее в этой главе, файлы также следует открывать в двоичном режиме. Объявление объекта fstream позволяет открыть фар1л для чтения и записи. При этом необходимо задать достаточное количество флагов режима, чтобы файловая система знала, будет ли файл использоваться для чтения и/или записи. Чтобы переключиться с вывода на ввод, необходимо либо записать текущее содержимое буфера, либо изменить текущую позицию в файле. Чтобы переключиться с ввода на вывод, измените текущую позицию. Если вы хотите создать файл при объявлении объекта fstream, укажите режим открытия ios::trunc при вызове конструктора.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |