1. Главная страница » Компьютеры

Ifstream c описание функций

Автор: | 16.12.2019

БлогNot. Лекции по C/C++: работа с файлами (fstream)

Лекции по C/C++: работа с файлами (fstream)

Механизм ввода-вывода, разработанный для обычного языка С, не соответствует общепринятому сегодня стилю объектно-ориентированного программирования, кроме того, он активно использует операции с указателями, считающиеся потенциально небезопасными в современных защищённых средах выполнения кода. Альтернативой при разработке прикладных приложений является механизм стандартных классов ввода-вывода, предоставляемый стандартом языка C++.

Наиболее часто применяются классы ifstream для чтения, ofstream для записи и fstream для модификации файлов.

Все поточные классы ввода-вывода являются косвенными производными от общего предка ios , полностью наследуя его функциональность. Так, режим открытия файлов задает член данных перечисляемого типа open_mode, который определяется следующим образом:

Ниже приведены возможные значения флагов и их назначение.

Режим Назначение
in Открыть для ввода (выбирается по умолчанию для ifstream)
out Открыть для вывода (выбирается по умолчанию для ofstream)
binary Открыть файл в бинарном виде
aрр Присоединять данные; запись в конец файла
ate Установить файловый указатель на конец файла
trunc Уничтожить содержимое, если файл существует (выбирается по умолчанию, если флаг out указан, а флаги ate и арр — нет)

Например, чтобы открыть файл с именем test.txt для чтения данных в бинарном виде, следует написать:

Оператор логического ИЛИ ( | ) позволяет составить режим с любым сочетанием флагов. Так, чтобы, открывая файл по записи, случайно не затереть существующий файл с тем же именем, надо использовать следующую форму:

Предполагается, что к проекту подключён соответствующий заголовочный файл:

Читайте также:  Asus rt n18u iptv

Для проверки того удалось ли открыть файл, можно применять конструкцию

Операторы включения и извлечения

Переопределённый в классах работы с файлами оператор включения ( ) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

Можно также записывать текстовую строку по частям:

Оператор endl завершает ввод строки символом "возврат каретки":

С помощью оператора включения несложно записывать в файл значения переменных или элементов массива:

В результате выполнения кода образуется три строки текстового файла Temp.txt :

Обратите внимание, что числовые значения записываются в файл в виде текстовых строк, а не двоичных значений.

Оператор извлечения ( >> )производит обратные действия. Казалось бы, чтобы извлечь символы из файла Temp.txt , записанного ранее, нужно написать код наподобие следующего:

Однако оператор извлечения остановится на первом попавшемся разделителе (символе пробела, табуляции или новой строки). Таким образом, при разборе предложения "Текстовый массив содержит переменные" только слово "Текстовый" запишется в массив buff , пробел игнорируется, а слово "массив" станет значением целой переменной vx и исполнение кода "пойдет вразнос" с неминуемым нарушением структуры данных. Далее, при обсуждении класса ifstream , будет показано, как правильно организовать чтение файла из предыдущего примера.

Класс ifstream: чтение файлов

Как следует из расшифровки названия, класс ifstream предназначен для ввода файлового потока. Далее перечислены основные методы класса. Большая часть из них унаследована от класса istream и перегружена с расширением родительской функциональности. К примеру, функция get , в зависимости от параметра вызова, способна считывать не только одиночный символ, но и символьный блок.

Метод Описание
open Открывает файл для чтения
get Читает один или более символов из файла
getline Читает символьную строку из текстового файла или данные из бинарного файла до определенного ограничителя
read Считывает заданное число байт из файла в память
eof Возвращает ненулевое значение (true), когда указатель потока достигает конца файла
peek Выдает очередной символ потока, но не выбирает его
seekg Перемещает указатель позиционирования файла в заданное положение
tellg Возвращает текущее значение указателя позиционирования файла
close Закрывает файл

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

Метод getline прочитает первую строку файла до конца, а оператор >> присвоит значения переменным.

Следующий пример показывает добавление данных в текстовый файл с последующим чтением всего файла. Цикл while (1) используется вместо while(!file2.eof()) по причинам, которые обсуждались в предыдущей лекции.

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

Этот код под ОС Windows также зависит от наличия в последней строке файла символа перевода строки, надежнее было бы сделать так:

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

Вместо метода close можно использовать оператор delete , который автоматически вызовет деструктор объекта file и закроет файл. Код цикла while обеспечивает надлежащую проверку признака конца файла.

Класс ofstream: запись файлов

Класс ofstream предназначен для вывода данных из файлового потока. Далее перечислены основные методы данного класса.

Метод Описание
open Открывает файл для записи
put Записывает одиночный символ в файл
write Записывает заданное число байт из памяти в файл
seekp Перемещает указатель позиционирования в указанное положение
tellp Возвращает текущее значение указателя позиционирования файла
close Закрывает файл

Описанный ранее оператор включения удобен для организации записи в текстовый файл:

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

Первый параметр методов write и read (адрес блока записи/чтения) должен иметь тип символьного указателя char * , поэтому необходимо произвести явное преобразование типа адреса структуры void * . Второй параметр указывает, что бинарные блоки файла имеют постоянный размер байтов независимо от фактической длины записи. Следующее приложение дает пример создания и отображения данных простейшей записной книжки. Затем записи файла последовательно считываются и отображаются на консоли.

В результате выполнения этого кода образуется бинарный файл Notebook.dat из трех блоков размером по 80 байт каждый (при условии, что символы — однобайтовые). Естественно, вы можете использовать другие поточные методы и проделывать любые операции над полями определенной структуры данных.

Класс fstream: произвольный доступ к файлу

Предположим что в нашей записной книжке накопилось 100 записей, а мы хотим считать 50-ю. Конечно, можно организовать цикл и прочитать все записи с первой по заданную. Очевидно, что более целенаправленное решение — установить указатель позиционирования файла pos прямо на запись 50 и считать ее:

Подобные операции поиска эффективны, если файл состоит из записей известного и постоянного размера. Чтобы заменить содержимое произвольной записи, надо открыть поток вывода в режиме модификации:

Если не указать флаг ios::ate (или ios::app ), то при открытии бинарного файла Notebook.dat его предыдущее содержимое будет стерто!

Наконец, можно открыть файл одновременно для чтения/записи, используя методы, унаследованные поточным классом fstream от своих предшественников. Поскольку класс fstream произведен от istream и ostream (родителей ifstream и ofstream соответственно), все упомянутые ранее методы становятся доступными в приложении.

В следующем примере показана перестановка первой и третьей записей файла Notebook.dat .

В конструкторе объекта file надо указать флаги ios::in и ios::out , разрешая одновременное выполнение операций чтения и записи. В результате выполнения этого кода первая и третья записи бинарного файла Notebook.dat поменяются местами.

Дополнительные примеры по теме есть в этой заметке.

Оглавление серии

05.11.2015, 09:45; рейтинг: 103544

  • atomic (C++11)
  • condition_variable (C++11)
  • future (C++11)
  • mutex (C++11)
  • shared_mutex (C++14)
  • thread (C++11)
  • cassert
  • cctype
  • cerrno
  • cfenv (C++11)
  • cfloat
  • cinttypes (C++11)
  • ciso646
  • climits
  • clocale
  • cmath
  • csetjmp
  • csignal
  • cstdarg
  • cstdbool (C++11)
  • cstddef
  • cstdint (C++11)
  • cstdio
  • cstdlib
  • cstring
  • ctgmath (C++11)
  • ctime
  • cuchar (C++11)
  • cwchar
  • cwctype

fstream (сокращение от «FileStream») — заголовочный файл из стандартной библиотеки C++, включающий набор классов, методов и функций, которые предоставляют интерфейс для чтения/записи данных из/в файл. Для манипуляции с данными файлов используются объекты, называемые потоками («stream»).

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

Общедоступные функции [ править | править код ]

Это корневые функции библиотеки, не вошедшие ни в один из основных классов. Они используются довольно часто и могут быть применимы ко всем объектам потоков в каждом из классов.

  • rdbuf . Все объекты fstream могут быть ассоциированы с объектом буфера файлов filebuf . Чтобы сопоставить объект класса fstream с объектом буфера, используют функцию rdbuf (без аргументов). Объект буфера предоставляет намного большие возможности по управлению данными в файле, чем стандартные функции подклассов fstream .
  • open() . Этим методом можно открыть заданный файл, сопоставив его с одним из объектов потока[1]. В зависимости от передаваемых аргументов, файл может быть открыт для чтения, для записи (либо для полной, либо для добавления данных), как бинарный, или как текстовый файл.
  • is_open() . Функция, определяющая, открыт ли в данный момент файл, которому сопоставлен определенный объект потока. Возвращает булевское значение. Используется в основном для предотвращения ошибок доступа при попытке открыть уже использующийся файл. Без аргументов.
  • close() . Функция закрывает файл, то есть прекращает доступ к нему, таким образом освобождая его для других функций или программ.

Файлы позволяют пользователю считывать большие объемы данных непосредственно с диска, не вводя их с клавиатуры. Существуют два основных типа файлов: текстовые и двоичные.

Текстовыми называются файлы, состоящие из любых символов. Они организуются по строкам, каждая из которых заканчивается символом «конца строки». Конец самого файла обозначается символом «конца файла». При записи информации в текстовый файл, просмотреть который можно с помощью любого текстового редактора, все данные преобразуются к символьному типу и хранятся в символьном виде.

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

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

В программах на C++ при работе с текстовыми файлами необходимо подключать библиотеки iostream и fstream.

Для того чтобы записывать данные в текстовый файл, необходимо:

  1. описать переменную типа ofstream.
  2. открыть файл с помощью функции open.
  3. вывести информацию в файл.
  4. обязательно закрыть файл.

Для считывания данных из текстового файла, необходимо:

  1. описать переменную типа ifstream.
  2. открыть файл с помощью функции open.
  3. считать информацию из файла, при считывании каждой порции данных необходимо проверять, достигнут ли конец файла.
  4. закрыть файл.

Запись информации в текстовый файл

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

ofstream F;

Будет создана переменная F для записи информации в файл. На следующим этапе файл необходимо открыть для записи. В общем случае оператор открытия потока будет иметь вид:

F.open(«file», mode);

Здесь F — переменная, описанная как ofstream, file — полное имя файла на диске, mode — режим работы с открываемым файлом. Обратите внимание на то, что при указании полного имени файла нужно ставить двойной слеш. Для обращения, например к файлу accounts.txt, находящемуся в папке sites на диске D, в программе необходимо указать: D:\sites\accounts.txt.

Файл может быть открыт в одном из следующих режимов:

  • ios::in — открыть файл в режиме чтения данных; режим является режимом по умолчанию для потоков ifstream;
  • ios::out — открыть файл в режиме записи данных (при этом информация о существующем файле уничтожается); режим является режимом по умолчанию для потоков ofstream;
  • ios::app — открыть файл в режиме записи данных в конец файла;
  • ios::ate — передвинуться в конец уже открытого файла;
  • ios::trunc — очистить файл, это же происходит в режиме ios::out;
  • ios::nocreate — не выполнять операцию открытия файла, если он не существует;
  • ios::noreplace — не открывать существующий файл.

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

После удачного открытия файла (в любом режиме) в переменной F будет храниться true, в противном случае false. Это позволит проверить корректность операции открытия файла.

Открыть файл (в качестве примера возьмем файл D:\sites\accounts.txt) в режиме записи можно одним из следующих способов:

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

Если вы хотите открыть существующий файл в режиме дозаписи, то в качестве режима следует использовать значение ios::app.

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

Например, для записи в поток F переменной a, оператор вывода будет иметь вид:

F #include «stdafx.h»
#include
#include
#include
using namespace std ;
int main ( )
<
setlocale ( LC_ALL, «RUS» ) ;
int i, n ;
double a ;
//описывает поток для записи данных в файл
ofstream f ;
//открываем файл в режиме записи,
//режим ios::out устанавливается по умолчанию
f. open ( «D: \ sites \ accounts.txt» , ios :: out ) ;
//вводим количество вещественных чисел
cout «n=» ; cin >> n ;
//цикл для ввода вещественных чисел
//и записи их в файл
for ( i = 0 ; i n ; i ++ )
<
cout «a=» ;
//ввод числа
cin >> a ;
f a « « ;
>
//закрытие потока
f. close ( ) ;
system ( «pause» ) ;
return 0 ;
>

Чтение информации из текстового файла

Для того чтобы прочитать информацию из текстового файла, необходимо описать переменную типа ifstream. После этого нужно открыть файл для чтения с помощью оператора open. Если переменную назвать F, то первые два оператора будут такими:

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

Например, для чтения данных из потока F в переменную a, оператор ввода будет выглядеть так:

F>>a;

Два числа в текстовом редакторе считаются разделенными, если между ними есть хотя бы один из символов: пробел, табуляция, символ конца строки. Хорошо, когда программисту заранее известно, сколько и какие значения хранятся в текстовом файле. Однако часто известен лишь тип значений, хранящихся в файле, при этом их количество может быть различным. Для решения данной проблемы необходимо считывать значения из файла поочередно, а перед каждым считыванием проверять, достигнут ли конец файла. А поможет сделать это функция F.eof(). Здесь F — имя потока функция возвращает логическое значение: true или false, в зависимости от того достигнут ли конец файла.

Следовательно, цикл для чтения содержимого всего файла можно записать так:

Для лучшего усвоения материала рассмотрим задачу.

Задача 2

В текстовом файле D:\game\accounts.txt хранятся вещественные числа, вывести их на экран и вычислить их количество.

Решение

На этом относительно объемный урок по текстовым файлам закончен. В следующей статье будут рассмотрены методы манипуляции, при помощи которых в C++ обрабатываются двоичные файлы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *