Как передать файл в функцию c

Обновлено: 04.07.2024

Блог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 для чтения данных в бинарном виде, следует написать:

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

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

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

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

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

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

Оператор 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()) по причинам, которые обсуждались в предыдущей лекции.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Для работы с файлами необходимо подключить заголовочный файл <fstream> . В нем определены несколько классов и подключены заголовочные файлы

Файловый ввод-вывод аналогичен стандартному вводу-выводу, единственное отличие – это то, что ввод-вывод выполнятся не на экран, а в файл.

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

При работе с файлом можно выделить следующие этапы:

  • создать объект класса fstream (возможно, ofstream или ifstream );
  • связать объект класса fstream с файлом, который будет использоваться для операций ввода-вывода;
  • осуществить операции ввода-вывода в файл;
  • закрыть файл.

Работа с файлами в C++

В результате будет создан файл

Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе ios предусмотрены константы, которые определяют режим открытия файлов.

Константа Описание
ios::in открыть файл для чтения
ios::out открыть файл для записи
ios::ate при открытии переместить указатель в конец файла
ios::app открыть файл для записи в конец файла
ios::trunc удалить содержимое файла, если он существует
ios::binary открытие файла в двоичном режиме

Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове метода open() .

ofstream fout( "file.txt" , ios::app);
fout.open( "file.txt" , ios::app);

Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции ИЛИ | , например:

ios::out | ios::in - открытие файла для записи и чтения.

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

Система ввода-вывода С++ позволяет осуществлять произвольный доступ с использованием методов seekg() и seekp() .

  • ifstream &seekg(Смещение, Позиция);
  • ofstream &seekp(Смещение, Позиция);

Смещение определяет область значений в пределах файла ( long int ).

Система ввода-вывода С++ обрабатывает два указателя, ассоциированные с каждым файлом:

  • get pointer g - определяет, где именно в файле будет производиться следующая операция ввода;
  • put pointer p - определяет, где именно в файле будет производиться следующая операция вывода.

Позиция смещения определяется как

Позиция Значение
ios::beg Начало файла
ios::cur Текущее положение
ios::end Конец файла

Всякий раз, когда осуществляются операции ввода или вывода, соответствующий указатель автоматически перемещается.
С помощью методов seekg() и seekp() можно получить доступ к файлу в произвольном месте.

Можно определить текущую позицию файлового указателя, используя следующие функции:

  • streampos tellg() - позиция для ввода
  • streampos tellp() - позиция для вывода

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

Вторая часть программы выведет в консоль

Ещё один пример. Допустим, нам нужно заполнять таблицу

Причем каждая вновь введенная строка должна размещаться в таблице непосредственно под "шапкой".

Алгоритм решения задачи следующий:

  • формируем очередную строку для вывода
  • открываем файл для чтения, считываем из него данные и сохраняем их в массив строк
  • закрываем файл
  • открываем файл для записи
  • выводим "шапку" таблицы
  • выводим новую строку
  • выводим все сохраненные строки обратно в файл, начиная со строки после шапки
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

fstream inOut;
inOut.open( "file.txt" , ios::in); // открываем файл для ввода
// Считываем из файла имеющиеся данные
int count = 0;
while (inOut.getline(line[count], 100)) count++;
inOut.close(); // закрываем файл


Результат выполнения:


Файл данных

Полученный файл данных:

Здравствуйте Елена. Скажите, а можно ли как то узнать наступивший конец файла. Например, если количество строк в файле неизвестно, а нужно организовать цикл по их считыванию и прервать его по окончанию файла. Елена, здравствуйте! Помогите, пожалуйста. Есть код, работающий, но вывод делает в консоль, а так как вывод очень большой, то все результаты там не помещаются, только малая последняя часть. Подскажите, пожалуйста, где и что изменить, чтоб вывод записывало в файл. Если можно очень подробно или прям конкретным примером, я со всем этим только только столкнулась, поэтому пока не особо соображаю(( Вот мой код 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import static java.lang.System.out;
import java.util.Arrays;
class Combinations
private static final int M = 12;
private static final int N = 24;
private static int [] generateCombinations( int [] arr)
if (arr == null)
arr = new int [M];
for ( int i = 0; i < M; i++)
arr[i] = i + 1;
return arr;
>
for ( int i = M - 1; i >= 0; i--)
if (arr[i] < N - M + i + 1)
arr[i]++;
for ( int j = i; j < M - 1; j++)
arr[j + 1] = arr[j] + 1;
return arr;
>
return null;
>
public static void main(String args[])
int [] arr = null;
while ((arr = generateCombinations(arr)) != null)
out.println(Arrays.toString(arr));
>
>
В настройках консоли (меню в верхнем левом углу) изменить размер буфера Думаю, что "в правильную". Можно попробовать взять, например, среднее арифметическое для каждой точки из двух файлов. Но это нужно анализировать при отладке. Елена, здравствуйте, с вами можно как-то связаться, помимо того как здесь в комментариях? Можно через форму обратной связи на сайте или через ВК Елена, здравствуйте. Подскажите, пожалуйста, как можно сделать так, чтобы из первой строки файла считывался размер массива, а из второй - его элементы, количество которых равно значению из первой строки. Не нашла у вас на сайте ничего про построчный ввод из файла. Заранее спасибо. Ввод из файла осуществляется аналогично консольному вводу. После считывания порции данных указатель позиции файла автоматически перемещается на ее конец. Да, но у вас в статьях нет ничего про, к примеру, getline. По вашим статьям я изучаю практически все, очень понятно и доходчиво написано, но этот блок то ли я не могу найти, то ли его нет. Подскажите, у вас на сайте есть статья, где более подробно описывается файловый ввод и вывод? Здравствуйте, попыталась сделать вывод данных в файл, но почему то только создался документ, а данных там нет. Что не так?

ofstream fout( "file.txt" , ios::out);
fout.open( "file.txt" , ios::out);
for ( int i = 0; i < SIZE; i++)
for ( int j = 0; j < SIZE; j++)
printf( "%5d " , a[i][j]);
printf( "\n" );

Вы выводите в файл указатель на строку, а не элементы матрицы Не совсем понимаю цель этого действия. Почему нельзя создать пустую строку? А вообще sr[0]=0; И ещё один вопрос. Можно ли ввести несколько слов с консоли в одно значение char? Можно ли как-то скопировать половину строки ? Выше вы копировали от середины и до конца, но мне нужно наоборот- от начала до середины ( или 10-го символа) Вроде рассмотрены оба варианта: поиск позиции от начала строки и от конца Не совсем правильно сформулировала , от определённого индекса до определённого индекса. То есть, у нас есть строка(char sr[50]="blablablabla";) Я хочу скопировать с третього индекса по 10. Мы с файлом работе м или со строкой? Если со строкой, то функция strncpy(&sr[3], 7, dst); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 надо сделать типа чтобы еще можно было добавить людей в список и выровнять это все Почему файл объявлен как поток вывода, а открывается для ввода? Чему равен count? Где тут люди? Почему при вводе нет цикла? 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

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

Наиболее частые операции следующее:

    1. Методы проверки открыт ли файл is_open() и достигнут ли конец файла eof()
      1. Настройка форматированного вывода для >> с помощью width() и precision()
      1. Операции позиционирования tellg(), tellp() и seekg(), seekp()

      Это не все возможности, которые предоставляет библиотека fstream. Рассматривать все сейчас мы не будем, поскольку их круг применения достаточно узок. Познакомимся с вышеперечисленными. Начнем с класса чтения.

      Класс ifstream

      Открытие файла в конструкторе выглядит так:

      ifstream file ( "d:\\1\\файл.txt" ) ; // открываем файл в конструкторе

      Так мы просим открыть файл txt с именем файл.txt, который лежит в папке с названием 1, а папка находится на диске d.

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

      Так все отработает нормально и файл откроется:

      библиотека fstream, работа с файлами в с++, программирование для начинающих

      Второй вариант проверки с использованием метода is_open() :

      Метод is_open() вернет 1, если файл найден и успешно открыт. Иначе вернет 0 и сработает код прописанный в блоке else .

      Если файл успешно открыт, из него можно производить чтение.

      Оператор считывания >>

      Так же как и в iostream считывание можно организовать оператором >> , который указывает в какую переменную будет произведено считывание:

      Считает вещественное, целое и строку. Считывание строки закончится, если появится пробел или конец строки. Стоит отметить, что оператор >> применяется к текстовым файлам. Считывание из бинарного файла производить лучше всего с помощью метода read().

      Кстати этот оператор достаточно удобен, если стоит задача разделить файл на слова:

      Методы getline() и get()

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

      Если же читать нужно в массив символов char[], то либо get() либо getline() именно как методы:

      Принцип в общем тот же, что и в аналогах из iostream: Указывается в параметрах буфер (переменная, куда будет производиться чтение), или точнее указатель на блок памяти (если переменная объявлена статически: char buffer[255] к примеру, то пишется в параметры &buffer), указывается максимальное количество считываемого (в примере это n), дабы не произошло переполнение и выход за пределы буфера и по необходимости символ-разделитель, до которого будет считка (в примере это пробел). Надеюсь я не больно наступлю на хобот фанатикам Си, если сажу что эти две функции на 99% взаимозаменяемы, и на 95% могут быть заменены методом read() .

      Метод read()

      Похож на предыдущий пример?

      Метод close()

      Метод eof()

      Проверяет не достигнут ли конец файла. Т.е. можно ли из него продолжать чтение. Выше пример с считкой слов оператором >> как раз использует такую проверку.

      Метод seekg()

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

      Здравствуйте. Изучаю C++. Работаю с чтением и записью данных в файл. Напрямую написать реализацию в функции main смог. Но вот вынести в отдельные функции Создание файла, Запись данных и Считывание данных не могу. Видимо знаний не достаточно. Привожу код программы:


      Заранее Вам благодарен.

      Простой 4 комментария

      Но вот вынести в отдельные функции Создание файла, Запись данных и Считывание данных не могу.

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

      DimaLepel

      Я не знаю, какие параметры передавать в функции и возвращать.

      myjcom

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

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

      Что мне надо сделать? - Отрыть файл.
      Какой файл открыть? - Значит или путь файла известен внутри функции, или передается параметром.
      Для чего открыть файл: для записи или для чтения? - Видимо или функция должна своими именем об этом говорить, или режим работы с файлом надо передавать параметром.
      А что делать с дескриптором открытого в функции файла? - Возвращать, пожалуй.
      А что если файл не удалось открыть? - Наверное надо предусмотреть обработку ошибок и возвращать недействительный дескриптор файла.
      Зачем мне нужен дескриптор открытого файла? - Чтобы считать оттуда что-либо или записать туда что-либо.
      Что мне надо сделать чтобы считать из файла что-либо? - .
      Что мне надо сделать чтобы записать в файл что-либо? - .
      Что мне делать с дескриптором открытого файла когда он больше не нужен? - .

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

      1. std::ifstream, std::ofstream здесь - это Си++, всё остальное - это Си. Чтобы открыть с файл в Си используйте open.
      2. using namespace std; - это плохо
      3. Если цель писать на Си++, то в нем есть ссылки (помимо указателей); В Си есть указатели - используйте что-нибудь из этого, чтобы передать доступ к объекту в функцию
      4. Если использовать не std::ifstream & std::ofstream, а std::fstream, то через этот стрим можно будет и читать и писать
      5. Опять же - в Си++ есть std::string

      В общем, почитайте сначала чем Си отличается от Си++ - смешивать их не очень клёво

      Работа файлового ввода/вывода в языке C++ почти аналогична работе обычных потоков ввода/вывода (но с небольшими нюансами).

      Классы файлового ввода/вывода

      Есть три основных класса файлового ввода/вывода в языке C++:

      ofstream (является дочерним классу ostream);

      fstream (является дочерним классу iostream ).

      С помощью этих классов можно выполнить однонаправленный файловый ввод, однонаправленный файловый вывод и двунаправленный файловый ввод/вывод. Для их использования нужно всего лишь подключить заголовочный файл fstream.

      В отличие от потоков cout, cin, cerr и clog, которые сразу же можно использовать, файловые потоки должны быть явно установлены программистом. То есть, чтобы открыть файл для чтения и/или записи, нужно создать объект соответствующего класса файлового ввода/вывода, указав имя файла в качестве параметра. Затем, с помощью оператора вставки ( << ) или оператора извлечения ( >> ), можно записывать данные в файл или считывать содержимое файла. После проделывания данных действий нужно закрыть файл — явно вызвать метод close() или просто позволить файловой переменной ввода/вывода выйти из области видимости (деструктор файлового класса ввода/вывода закроет этот файл автоматически вместо нас).

      Файловый вывод

      Для записи в файл используется класс ofstream . Например:

      // Класс ofstream используется для записи данных в файл. // Если мы не можем открыть этот файл для записи данных, cerr << "Uh oh, SomeText.txt could not be opened for writing!" << endl ; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл

      Обратите внимание, мы также можем использовать метод put() для записи одного символа в файл.

      Файловый ввод

      Теперь мы попытаемся прочитать содержимое файла, который создали в предыдущем примере. Обратите внимание, ifstream возвратит 0 , если мы достигли конца файла (это удобно для определения «длины» содержимого файла). Например:

      // ifstream используется для чтения содержимого файла. // Если мы не можем открыть этот файл для чтения его содержимого, cerr << "Uh oh, SomeText.txt could not be opened for reading!" << endl ; // то перемещаем эти данные в строку, которую затем выводим на экран // Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл

      Результат выполнения программы:

      Хм, это не совсем то, что мы хотели. Как мы уже узнали на предыдущих уроках, оператор извлечения работает с «отформатированными данными», т.е. он игнорирует все пробелы, символы табуляции и символ новой строки. Чтобы прочитать всё содержимое как есть, без его разбивки на части (как в примере, приведенном выше), нам нужно использовать метод getline():

      // ifstream используется для чтения содержимого файлов. // Мы попытаемся прочитать содержимое файла SomeText.txt // Если мы не можем открыть файл для чтения его содержимого, cerr << "Uh oh, SomeText.txt could not be opened for reading!" << endl ; // то перемещаем то, что можем прочитать, в строку, а затем выводим эту строку на экран // Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл

      Результат выполнения программы:

      Буферизованный вывод

      Вывод в языке C++ может быть буферизован. Это означает, что всё, что выводится в файловый поток, не может сразу же быть записанным на диск (в конкретный файл). Это сделано, в первую очередь, по соображениям производительности. Когда данные буфера записываются на диск, то это называется очисткой буфера. Одним из способов очистки буфера является закрытие файла. В таком случае всё содержимое буфера будет перемещено на диск, а затем файл будет закрыт.

      Буферизация вывода обычно не является проблемой, но при определенных обстоятельствах она может вызвать проблемы у неосторожных новичков. Например, когда в буфере хранятся данные, а программа преждевременно завершает свое выполнение (либо в результате сбоя, либо путем вызова функции exit()). В таких случаях деструкторы классов файлового ввода/вывода не выполняются, файлы никогда не закрываются, буферы не очищаются и наши данные теряются навсегда. Вот почему хорошей идеей является явное закрытие всех открытых файлов перед вызовом функции exit().

      Также буфер можно очистить вручную, используя метод ostream::flush() или отправив std::flush в выходной поток. Любой из этих способов может быть полезен для обеспечения немедленной записи содержимого буфера на диск в случае сбоя программы.

      Интересный нюанс: Поскольку std::endl; также очищает выходной поток, то его чрезмерное использование (приводящее к ненужным очисткам буфера) может повлиять на производительность программы (так как очистка буфера в некоторых случаях может быть затратной операцией). По этой причине программисты, которые заботятся о производительности своего кода, часто используют \n вместо std::endl для вставки символа новой строки в выходной поток, дабы избежать ненужной очистки буфера.

      Режимы открытия файлов

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

      app — открывает файл в режиме добавления;

      ate — переходит в конец файла перед чтением/записью;

      binary — открывает файл в бинарном режиме (вместо текстового режима);

      in — открывает файл в режиме чтения (по умолчанию для ifstream );

      out — открывает файл в режиме записи (по умолчанию для ofstream );

      trunc — удаляет файл, если он уже существует.

      Можно указать сразу несколько флагов путем использования побитового ИЛИ (|).

      ifstream по умолчанию работает в режиме ios::in;

      ofstream по умолчанию работает в режиме ios::out;

      fstream по умолчанию работает в режиме ios::in ИЛИ ios::out, что означает, что вы можете выполнять как чтение содержимого файла, так и запись данных в файл.

      Читайте также: