Большинство компьютерных программ работают с файлами, и поэтому возникает необходимость создавать, удалять, записывать читать, открывать файлы. Что же такое файл? Файл – именованный набор байтов, который может быть сохранен на некотором накопителе.
Ну, теперь ясно, что под файлом понимается некоторая последовательность байтов, которая имеет своё, уникальное имя, например файл.txt . В одной директории не могут находиться файлы с одинаковыми именами. Под именем файла понимается не только его название, но и расширение, например: file.txt и file.dat — разные файлы, хоть и имеют одинаковые названия. Существует такое понятие, как полное имя файлов – это полный адрес к директории файла с указанием имени файла, например: D:docsfile.txt . Важно понимать эти базовые понятия, иначе сложно будет работать с файлами.
Для работы с файлами необходимо подключить заголовочный файл . В определены несколько классов и подключены заголовочные файлы — файловый ввод и — файловый вывод.
Файловый ввод/вывод аналогичен стандартному вводу/выводу, единственное отличие – это то, что ввод/вывод выполнятся не на экран, а в файл. Если ввод/вывод на стандартные устройства выполняется с помощью объектов cin и cout , то для организации файлового ввода/вывода достаточно создать собственные объекты, которые можно использовать аналогично операторам cin и cout .
Текстовые файлы в с++ | программа с использованием файлов
Например, необходимо создать текстовый файл и записать в него строку Работа с файлами в С++ . Для этого необходимо проделать следующие шаги:
- создать объект класса ofstream ;
- связать объект класса с файлом, в который будет производиться запись;
- записать строку в файл;
- закрыть файл.
Почему необходимо создавать объект класса ofstream , а не класса ifstream ? Потому, что нужно сделать запись в файл, а если бы нужно было считать данные из файла, то создавался бы объект класса ifstream .
// создаём объект для записи в файл ofstream /*имя объекта*/; // объект класса ofstream
Назовём объект – fout , Вот что получится:
ofstream fout;
Для чего нам объект? Объект необходим, чтобы можно было выполнять запись в файл. Уже объект создан, но не связан с файлом, в который нужно записать строку.
fout.open(«cppstudio.txt»); // связываем объект с файлом
Через операцию точка получаем доступ к методу класса open(), в круглых скобочках которого указываем имя файла. Указанный файл будет создан в текущей директории с программой. Если файл с таким именем существует, то существующий файл будет заменен новым. Итак, файл открыт, осталось записать в него нужную строку. Делается это так:
fout
Используя операцию передачи в поток совместно с объектом fout строка Работа с файлами в С++ записывается в файл. Так как больше нет необходимости изменять содержимое файла, его нужно закрыть, то есть отделить объект от файла.
fout.close(); // закрываем файл
Итог – создан файл со строкой Работа с файлами в С++ .
Шаги 1 и 2 можно объединить, то есть в одной строке создать объект и связать его с файлом. Делается это так:
Язык C++ с нуля | #12 Работа с файлами в c++ через ifstream и ofstream.
ofstream fout(«cppstudio.txt»); // создаём объект класса ofstream и связываем его с файлом cppstudio.txt
Объединим весь код и получим следующую программу.
// file.cpp: определяет точку входа для консольного приложения. #include «stdafx.h» #include using namespace std; int main(int argc, char* argv[]) < ofstream fout(«cppstudio.txt»); // создаём объект класса ofstream для записи и связываем его с файлом cppstudio.txt fout
Осталось проверить правильность работы программы, а для этого открываем файл cppstudio.txt и смотрим его содержимое, должно быть — Работа с файлами в С++ .
Для того чтобы прочитать файл понадобится выполнить те же шаги, что и при записи в файл с небольшими изменениями:
- создать объект класса ifstream и связать его с файлом, из которого будет производиться считывание;
- прочитать файл;
- закрыть файл.
// file_read.cpp: определяет точку входа для консольного приложения. #include «stdafx.h» #include #include using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, «rus»); // корректное отображение Кириллицы char buff[50]; // буфер промежуточного хранения считываемого из файла текста ifstream fin(«cppstudio.txt»); // открыли файл для чтения fin >> buff; // считали первое слово из файла cout
В программе показаны два способа чтения из файла, первый – используя операцию передачи в поток, второй – используя функцию getline() . В первом случае считывается только первое слово, а во втором случае считывается строка, длинной 50 символов. Но так как в файле осталось меньше 50 символов, то считываются символы включительно до последнего. Обратите внимание на то, что считывание во второй раз ( строка 17 ) продолжилось, после первого слова, а не с начала, так как первое слово было прочитано в строке 14 . Результат работы программы показан на рисунке 1.
CppStudio.com
Работа с файлами в С++ Для продолжения нажмите любую клавишу . . .
Рисунок 1 — Работа с файлами в С++
Программа сработала правильно, но не всегда так бывает, даже в том случае, если с кодом всё впорядке. Например, в программу передано имя несуществующего файла или в имени допущена ошибка. Что тогда? В этом случае ничего не произойдёт вообще. Файл не будет найден, а значит и прочитать его не возможно.
Поэтому компилятор проигнорирует строки, где выполняется работа с файлом. В результате корректно завершится работа программы, но ничего, на экране показано не будет. Казалось бы это вполне нормальная реакции на такую ситуацию. Но простому пользователю не будет понятно, в чём дело и почему на экране не появилась строка из файла.
Так вот, чтобы всё было предельно понятно в С++ предусмотрена такая функция — is_open() , которая возвращает целые значения: 1 — если файл был успешно открыт, 0 — если файл открыт не был. Доработаем программу с открытием файла, таким образом, что если файл не открыт выводилось соответствующее сообщение.
Результат работы программы показан на рисунке 2.
CppStudio.com
Файл не может быть открыт! Для продолжения нажмите любую клавишу . . .
Рисунок 2 — Работа с файлами в С++
Как видно из рисунка 2 программа сообщила о невозможности открыть файл. Поэтому, если программа работает с файлами, рекомендуется использовать эту функцию, is_open() , даже, если уверены, что файл существует.
Режимы открытия файлов
Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе ios_base предусмотрены константы, которые определяют режим открытия файлов (см. Таблица 1).
ios_base::in | открыть файл для чтения |
ios_base::out | открыть файл для записи |
ios_base::ate | при открытии переместить указатель в конец файла |
ios_base::app | открыть файл для записи в конец файла |
ios_base::trunc | удалить содержимое файла, если он существует |
ios_base::binary | открытие файла в двоичном режиме |
Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове функции open() .
ofstream fout(«cppstudio.txt», ios_base::app); // открываем файл для добавления информации к концу файла fout.open(«cppstudio.txt», ios_base::app); // открываем файл для добавления информации к концу файла
Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции или | , например: ios_base::out | ios_base::trunc — открытие файла для записи, предварительно очистив его.
Объекты класса ofstream , при связке с файлами по умолчанию содержат режимы открытия файлов ios_base::out | ios_base::trunc . То есть файл будет создан, если не существует. Если же файл существует, то его содержимое будет удалено, а сам файл будет готов к записи. Объекты класса ifstream связываясь с файлом, имеют по умолчанию режим открытия файла ios_base::in — файл открыт только для чтения.
Режим открытия файла ещё называют — флаг, для удобочитаемости в дальнейшем будем использовать именно этот термин. В таблице 1 перечислены далеко не все флаги, но для начала этих должно хватить.
Обратите внимание на то, что флаги ate и app по описанию очень похожи, они оба перемещают указатель в конец файла, но флаг app позволяет производить запись, только в конец файла, а флаг ate просто переставляет флаг в конец файла и не ограничивает места записи.
Разработаем программу, которая, используя операцию sizeof() , будет вычислять характеристики основных типов данных в С++ и записывать их в файл. Характеристики:
- число байт, отводимое под тип данных
- максимальное значение, которое может хранить определённый тип данных.
Запись в файл должна выполняться в таком формате:
/* data type byte max value bool = 1 255.00 char = 1 255.00 short int = 2 32767.00 unsigned short int = 2 65535.00 int = 4 2147483647.00 unsigned int = 4 4294967295.00 long int = 4 2147483647.00 unsigned long int = 4 4294967295.00 float = 4 2147483647.00 long float = 8 9223372036854775800.00 double = 8 9223372036854775800.00 */
Такая программа уже разрабатывалась ранее в разделе Типы данных С++ , но там вся информация о типах данных выводилась на стандартное устройство вывода, а нам необходимо программу переделать так, чтобы информация записывалась в файл. Для этого необходимо открыть файл в режиме записи, с предварительным усечением текущей информации файла (строка 14). Как только файл создан и успешно открыт (строки 16 — 20), вместо оператора cout , в строке 22 используем объект fout . таким образом, вместо экрана информация о типах данных запишется в файл.
// write_file.cpp: определяет точку входа для консольного приложения. #include «stdafx.h» #include #include // работа с файлами #include // манипуляторы ввода/вывода using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, «rus»); // связываем объект с файлом, при этом файл открываем в режиме записи, предварительно удаляя все данные из него ofstream fout(«data_types.txt», ios_base::out | ios_base::trunc); if (!fout.is_open()) // если файл небыл открыт < cout fout << » data type » << «byte» << » » << » max value » << endl // заголовки столбцов << «bool = » << sizeof(bool) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) — 1) << endl << «char = » << sizeof(char) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) — 1) << endl << «short int = » << sizeof(short int) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 — 1) — 1) << endl << «unsigned short int = » << sizeof(unsigned short int) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) — 1) << endl << «int = » << sizeof(int) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 — 1) — 1) << endl << «unsigned int = » << sizeof(unsigned int) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) — 1) << endl << «long int = » << sizeof(long int) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 — 1) — 1) << endl << «unsigned long int = » << sizeof(unsigned long int) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) — 1) << endl << «float = » << sizeof(float) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 — 1) — 1) << endl << «long float = » << sizeof(long float) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 — 1) — 1) << endl << «double = » << sizeof(double) << » » << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 — 1) — 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout
Нельзя не заметить, что изменения в программе минимальны, а всё благодаря тому, что стандартный ввод/вывод и файловый ввод/вывод используются абсолютно аналогично. В конце программы, в строке 45 мы явно закрыли файл, хотя это и не обязательно, но считается хорошим тоном программирования. Стоит отметить, что все функции и манипуляторы используемые для форматирования стандартного ввода/вывода актуальны и для файлового ввода/вывода. Поэтому не возникло никаких ошибок, когда оператор cout был заменён объектом fout .
Источник: cppstudio.com
Ofstream 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(); // закрываем файл >
Источник: metanit.com
Функции-члены потока выходного файла
Функции-члены потока вывода делятся на три типа: эквивалентные манипуляторам, выполняющие неформатированные операции записи и изменяющие состояние потока другим образом и при этом не имеющие эквивалентных манипуляторов или операторов вставки. Для последовательного форматированного вывода можно использовать только операторы вставки и манипуляторы. Для двоичного дискового вывода с произвольным доступом следует использовать другие функции-члены с операторами вставки или без них.
Функция 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 *) >
Функция 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 , так как он не проверяет конец файла.
Источник: learn.microsoft.com