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(); // закрываем файл >
Файловый ввод-вывод в C++
В языке C++ ввод-вывод осуществляется через объекты классов ifstream (для чтения данных) и ofstream (для вывода данных). Эти классы объявлены в заголовочном файле fstream .
При создании этих объектов нужно передать в конструктор один параметр — имя файла.
После этого с этими объектами можно работать точно так же, как с объектами cin и сout .
После окончания работы с файлами, файлы нужно «закрыть» эти объекты, вызвав для них метод close() .
Приведем пример программы, которая считывает два числа из файла с именем input.txt и выводит результат в файл output.txt .
#include
using namespace std;
int main()
ifstream fin(«input.txt»);
ofstream fout(«output.txt»);
int a, b;
fin >> a >> b;
fout fin.close();
fout.close();
>
Аналогично для считывания строки до символа конца строки из файла можно использовать функцию getline с двумя параметрами — файловый объект, из которого читаются данные и строка, куда записывается результат. Например:
Для проверки состояния файла можно использовать метод файла eof() . Он возвращает значение true или false в зависимости от того, был ли обнаружен конец файла при чтении:
Но при использовании этого метода могут возникнуть затруднения, например, с тем, что если после последнего числа в файле стоит символ конца строки, то состояние «достигнут конец файла» произойдет не после чтения последнего числа, а после следующего чтения.
Более надежный (и простой!) способ считать последовательность чисел из файла до конца файла — использование значения, возвращаемого при считывании:
Include fstream c что это
Потоки для работы с текстовыми файлами представляют объекты, для которых не задан режим открытия ios::binary .
Запись в файл
Для записи в файл к объекту ofstream или fstream применяется оператор
#include #include int main() < std::ofstream out; // поток для записи out.open("hello.txt"); // открываем файл для записи if (out.is_open()) < out out.close(); std::cout
Здесь предполагается, что файла «hello.txt» располагается в одной папке с файлом программы. Данный способ перезаписывает файл заново. Если надо дозаписать текст в конец файла, то для открытия файла нужно использовать режим ios::app :
std::ofstream out("hello.txt", std::ios::app); if (out.is_open()) < out out.close();
Чтение из файла
Если надо считать всю строку целиком или даже все строки из файла, то лучше использовать встроенную функцию getline() , которая принимает поток для чтения и переменную, в которую надо считать текст:
#include #include #include // для std::getline int main() < std::string line; std::ifstream in("hello.txt"); // окрываем файл для чтения if (in.is_open()) < while (std::getline(in, line)) < std::cout > in.close(); // закрываем файл >
Также для чтения данных из файла для объектов ifstream и fstream может применяться оператор >> (также как и при чтении с консоли):
#include #include #include struct Point < Point(double x, double y): x, y <> double x; double y; >; int main() < std::vectorpoints< Point, Point, Point>; std::ofstream out("points.txt"); if (out.is_open()) < // записываем все объекты Point в файл for (const Point& point: points) < out > out.close(); std::vector new_points; std::ifstream in("points.txt"); // окрываем файл для чтения if (in.is_open()) < double x, y; while (in >> x >> y) < new_points.push_back(Point); > > in.close(); for (const Point& point: new_points) < std::cout >
Здесь вектор структур Point записывается в файл.
for (const Point& point: points)
При чем при записи значений переменных файл они отделяются пробелом. В итоге будет создаваться файл в формате
0 0 4 5 -5 7
Используя оператор >>, можно считать последовательно данные в переменные x и y и ими инициализировать структуру.
double x, y; while (in >> x >> y) < new_points.push_back(Point); >
Но стоит отметить, что это ограниченный способ, поскольку при чтении файла поток in использует пробел для отделения одного значения от другого и таким образом считывает эти значения в переменные x и y. Если же нам надо записать и затем считать строку, которая содержит пробелы, и какие-то другие данные, то такой способ, конечно, не сработает.
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 [191139 просмотров]