Include fstream c что это
Перейти к содержимому

Include fstream c что это

  • автор:

Include fstream c что это

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

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

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

Открытие файлов

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

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

enum open_mode < app, binary, in, out, trunc, ate >;

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

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

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

ifstream file; file.open ("test.txt", ios::in | ios::binary);

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

ofstream file; file.open ("test.txt", ios::out | ios::app);

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

#include

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

if (!file) < //Обработка ошибки открытия файла >

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

file 

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

file 

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

file 

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

ofstream file ("Temp.txt"); char buff[] = "Текстовый массив содержит переменные"; int vx = 100; float pi = 3.14159; file 

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

Текстовый массив содержит переменные 100 3.14159

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

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

ifstream file ("Temp.txt"); char buff[100]; int vx; float pi; file >> buff >> vx >> pi;

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

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

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

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

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

ifstream file("Temp.txt"); char buff[100]; int vx; float pi; file.getline(buff, sizeof(buff)); file >> vx >> pi:

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

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

#include #include using namespace std; int main() < ofstream file; file.open("test.txt",ios::out|ios::app); if (!file) < cout for (int i=0; i int a,k=0; while (1) < file2 >> a; if (file2.eof()) break; cout cout 

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

while (1)

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

ifstream file("test.txt");

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

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

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

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

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

ofstream file ("temp.txt"); if (!file) return; for (int i=1; i

Бинарные файлы

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

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

#define _CRT_SECURE_NO_WARNINGS #include #include #include using namespace std; struct Notes < // структура данных записной книжки char Name[60]; // Ф.И.О. char Phone[16]; // телефон int Age; // возраст >; int main() < setlocale(LC_ALL, "Russian"); Notes Note1= < "Грозный Иоанн Васильевич", "не установлен", 60 >; Notes Note2= < "Годунов Борис Федорович ", "095-111-2233 ", 30 >; Notes Note3= < "Романов Петр Михайлович ", "812-333-2211 ", 20 >; ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof(Notes)); // 1-й блок ofile.write((char*)&Note2, sizeof(Notes)); // 2-й блок ofile.write((char*)&Note3, sizeof(Notes)); // 3-й блок ofile.close(); // закрыть записанный файл ifstream ifile("Notebook.dat", ios::binary); Notes Note; // структурированная переменная char str[80]; // статический буфер строки // Считывать и отображать строки в цикле, пока не eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) < sprintf(str, "%s\tТел: %s\tВозраст: %d", Note.Name, Note.Phone, Note.Age); cout ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; >

P.S. При выполнении этого и других листингов в Visual Studio последних версий может дополнительно понадобиться подключение директивы _CRT_SECURE_NO_WARNINGS.

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

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

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

ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Notes); ifile.seekg(pos); // поиск 50-й записи Notes Note; //Notes – описанная выше структура "запись" ifile.read((char*)&Note, sizeof(Notes));

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

ofstream ofilе ("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Notes); ofile.seekp(pos); // поиск 50-й записи Notes Note50 = ; ofile.write((char*)&Note, sizeof(Notes)); // замена

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

Дополнительно может понадобиться указать, откуда отсчитывается смещение.

f2.seekp(0, ios_base::beg); //ноль байт от начала файла

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

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

#include #include #include using namespace std; struct Notes < char Name[60]; char Phone[16]; int Age; >; int main() < setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Открыть файл на чтение/запись одновременно fstream file("Notebook.dat", ios::binary | ios::in | ios::out); file.seekg(2 * sizeof(Notes)); // найти и считать Note3 file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // найти и считать Note1 file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Note1 file.close(); cin.sync(); cin.get(); return 0; >

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

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

05.11.2015, 09:45 [190462 просмотра]

Ввод-вывод, оператор присваивания, арифметические операции

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

На самом деле, файловый ввод-вывод ничем не отличается от консольного. За единственным исключением – если данные читаются из файла, то в любой момент можно вернуться к началу файла и считать все заново.

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

После этого можно объявлять объекты, привязанные к файлам: для чтения данных из файла используются объекты типа ifstream (аббревиатура от input file stream, для записи данных в файл используются объекты типа ofstream (output file stream). Например

ifstream in; // Поток in будем использовать для чтения
ofstream out; // Поток out будем использовать для записи

Чтобы привязать тот или иной поток к файлу (открыть файл для чтения или для записи) используется метод open , которому необходимо передать параметр – текстовую строку, содержащую имя открываемого файла.

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

А чтобы считать значение переменной из потока in

Для закрытия ранее открытого файла используется метод close() без аргументов:

Закрытый файловый поток можно переоткрыть заново при помощи метода open , привязав его к тому же или другому файлу.

При считывании данных из файла может произойти ситуация достижения конца файла (end of file, сокращенно EOF). После достижения конца файла никакое чтение из файла невозможно. Для того, чтобы проверить состояние файла, необходимо вызвать метод eof() . Данный метод возвращает true , если достигнут конец файла или false , если не достигнут. Кроме того, состояние файлового потока можно проверить, если просто использовать идентификатор потока в качестве логического условия:

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

А организовать считывание файла построчно (считая, что строка заканчивается символом перехода на новую строку) так:

А еще полезно повторить листок "Строки".

Упражнения

  1. (A) Сумма Входной файл содержит два целых числа. Запишите в выходной файл их сумму.
  2. (B) Удалить лишние пробелы В файле записан текст, состоящий из строк. Удалите из каждой строки все лишние пробелы: лидирующие пробелы в начале каждой строки, концевые пробелы в конце строки, замените все пробелы между словами на один. Результат выведите в файл. Пример: input.txt У лукоморья
    дуб зеленый
    output.txt У лукоморья
    дуб зеленый
  3. (C) Выравнивание по левому краю Первая строка входного файла содержит целое число N. Далее (начиная со следующей строки) идет текст. Необходимо данный текст разбить на строки, длина которых не превосходит N и вывести его в файл. В каждой выведенной строке не должно быть пробелов в начале строки, пробелов в конце строки, слова в строке должны разделяться одним пробелом. При этом каждая строка должна быть максимально длинной, то есть строки формируются по "жадному" принципу: добавляем слова из входного файла до тех пор, пока длина полученной строки не превышает N, после этого ставим разрыв строки. Гарантируется, что во входном файле нет слов длиннее N символов. Пример: input.txt 20
    Для того дорога и дана, чтоб души вниманье не дремало.
    Человеку важно знать немало, потому дорога и трудна.
    output.txt Для того дорога и
    дана, чтоб души
    вниманье не дремало.
    Человеку важно знать
    немало, потому
    дорога и трудна.
  4. (D) Выравнивание по правому краю Решите предыдущую задачу при условии, что текст должен быть выровнен по правому краю, то есть каждая строка в выводе должна иметь длину ровно N символов, в противном случае ее нужно дополнить в начале строки пробелами до длины N. Последний символ каждой строки должен быть непробельным. Пример: input.txt 20
    Для того дорога и дана, чтоб души вниманье не дремало.
    Человеку важно знать немало, потому дорога и трудна.
    output.txt Для того дорога и
    дана, чтоб души
    вниманье не дремало.
    Человеку важно знать
    немало, потому
    дорога и трудна.
  5. (E) Выравнивание по ширине Решите предыдущую задачу при условии, что текст в выводе программы должен быть выровнен по ширине: первый и последний символ строки должны быть непробельными, при необходимости между словами должны быть добавлены дополнительные пробелы, при этом количество пробелов между любыми двумя словами в одной строке не должно отличаться более, чем на 1. Последнюю строку в выводе должна быть выровнена по левому краю. Пример: input.txt 20
    Для того дорога и дана, чтоб души вниманье не дремало.
    Человеку важно знать немало, потому дорога и трудна.
    output.txt Для того дорога и
    дана, чтоб души
    вниманье не дремало.
    Человеку важно знать
    немало, потому
    дорога и трудна.
  6. (F) Частотная таблица - 1 Входной файл содержит некоторый текст. Для каждой буквы латинского алфавита посчитайте, сколько раз она встречается в тексте. Заглавные и строчные буквы считайте вместе, остальные символы игнорируйте. Программа должна вывести все буквы латинского алфавита (заглавные, от A до Z, по одной букве в строке), после этого на этой же строке количество появления этой буквы в исходном тексте. Пример: input.txt AaB

Include fstream c что это

Для работы с файлами в стандартной библиотеке определен заголовочный файл fstream , который определяет базовые типы для чтения и записи файлов. В частности, это:

  • ifstream : для чтения с файла
  • ofstream : для записи в файл
  • fstream : совмещает запись и чтение

Для работы с данными типа wchar_t для этих потоков определены двойники:

  • wifstream
  • wofstream
  • wfstream

Открытие файла

При операциях с файлом вначале необходимо открыть файл с помощью функции open() . Данная функция имеет две версии:

  • open(путь)
  • open(путь, режим)

Для открытия файла в функцию необходимо передать путь к файлу в виде строки. И также можно указать режим открытия. Список доступных режимов открытия файла:

  • ios::in : файл открывается для ввода (чтения). Может быть установлен только для объекта ifstream или fstream
  • ios::out : файл открывается для вывода (записи). При этом старые данные удаляются. Может быть установлен только для объекта ofstream или fstream
  • ios::app : файл открывается для дозаписи. Старые данные не удаляются.
  • ios::ate : после открытия файла перемещает указатель в конец файла
  • ios::trunc : файл усекается при открытии. Может быть установлен, если также установлен режим out
  • ios::binary : файл открывается в бинарном режиме

Если при открытии режим не указан, то по умолчанию для объектов ofstream применяется режим ios::out , а для объектов ifstream - режим ios::in . Для объектов fstream совмещаются режимы ios::out и ios::in .

std::ofstream out; // поток для записи out.open("hello1.txt"); // окрываем файл для записи std::ofstream out2; out2.open("hello2.txt", std::ios::app); // окрываем файл для дозаписи std::ofstream out3; out2.open("hello3.txt", std::ios::out | std::ios::trunc); // установка нескольких режимов std::ifstream in; // поток для чтения in.open("hello4.txt"); // окрываем файл для чтения std::fstream fs; // поток для чтения-записи fs.open("hello5.txt"); // окрываем файл для чтения-записи

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

fstream(путь) fstream(путь, режим)

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

std::ofstream out("hello.txt"); std::ifstream in("hello.txt"); std::fstream fs("hello.txt", std::ios::app);

В данном случае предполагается, что файл "hello.txt" располагается в той же папке, где и файл программы.

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

В процессе работы мы можем проверить, окрыт ли файл с помощью функции is_open() . Если файл открыт, то она возвращает true:

std::ifstream in; // поток для чтения in.open("hello.txt"); // окрываем файл для чтения // если файл открыт if (in.is_open())

Закрытие файла

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

#include #include int main() < std::ofstream out; // поток для записи out.open("hello.txt"); // окрываем файл для записи out.close(); // закрываем файл std::ifstream in; // поток для чтения in.open("hello.txt"); // окрываем файл для чтения in.close(); // закрываем файл std::fstream fs; // поток для чтения-записи fs.open("hello.txt"); // окрываем файл для чтения-записи fs.close(); // закрываем файл >

Функции-члены потока выходного файла

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

Функция open для потоков вывода

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

При открытии файла, связанного с выходным потоком, обычно указывается open_mode флаг. Эти флаги можно объединить, которые определяются как перечислители в ios классе, с побитовой оператором OR ( | ). См ios_base::openmode . список перечислителей.

Три типовые ситуации для потока вывода используют параметры режима:

    Создание файла. Если файл уже существует, старая версия удаляется.

ofstream ofile("FILENAME"); // Default is ios::out ofstream ofile("FILENAME", ios::out); // Equivalent to above 
ofstream ofile("FILENAME", ios::app); 
ofstream ofile(); ofile.open("FILE1", ios::in); // Do some output ofile.close(); // FILE1 closed ofile.open("FILE2", ios::in); // Do some more output ofile.close(); // FILE2 closed // When ofile goes out of scope it is destroyed. 

Функция put .

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

cout.put('A'); // Exactly one character written cout  

Функция write .

Функция write записывает блок памяти в выходной поток файлов. Аргумент length указывает количество записанных байт. Следующий пример создает файловый поток вывода и записывает в него двоичное значение структуры Date :

// write_function.cpp // compile with: /EHsc #include using namespace std; struct Date < int mo, da, yr; >; int main( ) < Date dt = < 6, 10, 92 >; ofstream tfile( "date.dat" , ios::binary ); tfile.write( (char *) &dt, sizeof dt ); > 

Функция write не останавливается, когда она достигает символа NULL , поэтому записывается полная структура класса. Функция имеет два аргумента: указатель char и количество символов для записи. Обратите внимание на обязательный приведение char * к адресу объекта структуры.

Функции seekp и tellp

Файловый поток вывода хранит внутренний указатель на позицию следующей записи данных. Функция-член seekp устанавливает этот указатель, предоставляя тем самым вывод произвольного доступа в дисковый файл. Функция-член tellp возвращает позицию в файле. Примеры, которые используют входной поток, эквиваленты seekp и tellp см. в разделе "Функции seekg и tellg функции".

Функция close для потоков вывода

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

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

Функции обработки ошибок

Используйте эти функции-члены для проверки на ошибки при записи в поток:

Функция Возвращаемое значение
bad Возвращается, если возникает true неустранимая ошибка.
fail Возвращается, если возникает true неустранимая ошибка или ожидаемое условие, например ошибка преобразования, или если файл не найден. Обработка часто возобновляется после вызова clear с нулевым аргументом.
good Возвращается true , если не удается установить условие ошибки (неустранимое или другое) и флаг конца файла не задан.
eof Возвращает состояние true конца файла.
clear Устанавливает внутреннее состояние ошибки. Если вызывается с аргументами по умолчанию, он очищает все биты ошибок.
[ rdstate ](basic-ios-class.md#rdstate Возвращает текущее состояние ошибки.

Оператор ! перегружен для выполнения той же функции, что fail и функция. Таким образом выражение:

if(!cout). 
if(cout.fail()). 

Оператор void*() перегружается в противоположность оператору ! . Таким образом, выражение:

if(cout). 
if(!cout.fail()). 

Оператор void*() не эквивалентен good , так как он не проверяет конец файла.

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

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