Ofstream c очистить файл перед записью

Обновлено: 03.07.2024

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

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

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

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

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

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

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

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

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

ofstream F; 5 Далее термин "поток" будет использоваться для указания переменной, описанной как ofstream, ifstream, iofstream , а термин "файл" для указания реального файла на диске.

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

Здесь F — переменная, описанная как ofstream, file — имя файла на диске, mode — режим работы с открываемым файлом.

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

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

Параметр mode может отсутствовать, в этом случае файл открывается в режиме по умолчанию для данного потока 7 ios::in — для потоков ifstream, ios::out — для потоков ofstream . .

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

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

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

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

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

Для последовательного вывода в поток G переменных b, c и d оператор вывода станет таким:

Закрытие потока осуществляется с помощью оператора:

В качестве примера рассмотрим следующую задачу.

Задача 7.1. Создать текстовый файл abc.txt и записать туда n вещественных чисел.

Текст программы с комментариями:

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

Здесь реализована проверка ввода последнего числа. После него символ табуляции отсутствует.

В результате работы программы будет создан текстовый файл abc.txt , который можно просмотреть средствами обычного текстового редактора (рис. 7.1,рис. 7.2).

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

Процесс работы программы к задаче 7.1. Ввод исходных данных.


Рис. 7.1. Процесс работы программы к задаче 7.1. Ввод исходных данных.

Текстовый файл abc.txt, созданный программой к задаче 7.1.


увеличить изображение
Рис. 7.2. Текстовый файл abc.txt, созданный программой к задаче 7.1.

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

8 Указание режима ios::in можно, конечно, опустить, ведь для потока ifstream значение ios::in является значением по умолчанию, тогда оператор open можно будет записать так F.open("abc.txt");

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

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

Для последовательного ввода из потока G в переменные b, с и d оператор ввода станет таким:

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

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

Здесь F — имя потока, функция возвращает логическое значение: true — если достигнут конец файла, если не достигнут функция возвращает значение false .

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

Рассмотрим следующую задачу.

abc.txt

Задача 7.2. В текстовом файле хранятся вещественные числа (рис. 7.2), вывести их на экран и вычислить их количество.

Текст программы с комментариями приведён ниже.

Результат работы программы к задаче 7.2:

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

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

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

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

abc.txt

Задача 7.3. В файле (рис. 7.2) хранится массив вещественных чисел, дописать в файл этот же массив, упорядочив его по возрастанию.

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

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

Работа файлового ввода/вывода в языке 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, что означает, что вы можете выполнять как чтение содержимого файла, так и запись данных в файл.

Блог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 соответственно), все упомянутые ранее методы становятся доступными в приложении.

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

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

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

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

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

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

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

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

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

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

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

ofstream F;

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

F.open(«file», mode);

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

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

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

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

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

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

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

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

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

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

Для последовательного вывода в поток G переменных b, c, d оператор вывода станет таким:

Закрытие потока осуществляется с помощью оператора:

F.close();

В качестве примера рассмотрим следующую задачу.

Задача 1

Создать текстовый файл D:\\sites\\accounts.txt и записать в него n вещественных чисел.

Решение

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

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

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

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

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

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

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

//организуем для чтения значений из файла, выполнение
//цикла прервется, когда достигнем конец файла,
//в этом случае F.eof() вернет истину
while ( ! F. eof ( ) )
<
//чтение очередного значения из потока F в переменную a
F >> a ;
//далее идет обработка значения переменной a
>

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

Задача 2

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

Решение

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

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

Подробное чтение и запись файла C ++ (ofstream, ifstream, fstream)

Рассматривая идеи программирования на C ++, каждое упражнение в основном использует ofstream, ifstream, fstream. Раньше я примерно знал его использование и значение. Прочитав несколько постов Дэниела в блоге, я организовал и резюмировал:

Здесь в основном обсуждается содержание fstream:

1. Откройте файл

В классе fstream функция-член open () реализует операцию открытия файла, тем самым связывая поток данных с файлом и считывая и записывая файл через объекты fstream, ifstream, fstream.

  1. <span style= "font-family:Times New Roman;font-size:16px;" >
  2. public member function
  3. void open ( constchar * filename,
  4. ios_base::openmode mode = ios_base::in | ios_base::out );
  5. void open( constwchar_t *_Filename,
  6. ios_base::openmode mode= ios_base::in | ios_base::out,
  7. int prot = ios_base::_Openprot);
  8. </span>

Параметры: имя файла Имя файла операции

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

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

Способ открытия файла определяется в классе ios (то есть базовом классе потокового ввода-вывода), есть несколько способов:

Эти методы могут использоваться в комбинации, в форме «или» операция («|»): например,

  1. ofstream out;
  2. out.open( "Hello.txt" , ios::in|ios::out|ios::binary) // Сделаем соответствующий выбор в соответствии с вашими потребностями

Атрибуты открытого файла также определены в классе ios:

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

Во многих программах вы можете встретить такое использование, как ofstream out ("Hello.txt"), ifstream in (". "), fstream foi (". "), и нет явного вызова open () Функция выполняет файловые операции и напрямую вызывает свой метод открытия по умолчанию. Поскольку функция open () вызывается в конструкторе класса потока и имеет тот же конструктор, вы можете напрямую использовать объект потока в файле здесь. Операция по умолчанию выглядит следующим образом:

  1. <span style= "font-family:Times New Roman;font-size:16px;" >
  2. ofstream out( ". " , ios::out);
  3. ifstream in( ". " , ios::in);
  4. fstream foi( ". " , ios::in|ios::out);
  5. </span>

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

2. Закройте файл

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

3. Чтение и запись текстовых файлов

Классы stream, ifstream и fstream являются производными от ostream, istream и iostream соответственно. Вот почему объекты fstream могут использовать члены своего родительского класса для доступа к данным.

В общем, мы будем использовать эти классы для взаимодействия с теми же функциями-членами (cin и cout), что и для консоли (console) для ввода и вывода. Как показано в следующем примере, мы используем перегруженный оператор вставки <<:

Чтение данных из файла также можно выполнить так же, как cin >>:

Приведенный выше пример читает содержимое текстового файла и выводит его на экран. Обратите внимание, что мы используем новую функцию-член с именем eof, которая наследуется ifstream от класса ios и возвращает true, когда достигнут конец файла.

Проверка государственных флагов

В дополнение к eof (), есть некоторые функции-члены, которые проверяют состояние потока (все возвращаемые значения, возвращаемые bool):

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

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

Если прочитанный файл достигает конца файла, верните true.

Это является наиболее распространенным: если вызов какой-либо из вышеперечисленных функций возвращает true, эта функция возвращает false

Для сброса флагов состояния, проверенных вышеупомянутыми функциями-членами, вы можете использовать функцию-член clear () без параметров.

Получите и поместите указатели потока (получите и поместите указатели потока)

Все объекты потока ввода / вывода (объекты потоков ввода / вывода) имеют по крайней мере один указатель потока:

  • ifstream, как и istream, имеет указатель, называемый get указатель, который указывает на следующий элемент для чтения.
  • ofstream, как и ostream, имеет указатель пут указатель, который указывает на место, где записан следующий элемент.
  • fstream, похожий на iostream, наследует как get, так и put

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

Эти две функции-члены не должны передавать параметры и возвращать значение типа pos_type (в соответствии со стандартом ANSI-C ++), которое представляет собой целое число, представляющее позицию текущего указателя потока get (с помощью tellg) или указателя потока put (с помощью tellp).

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

seekg ( pos_type position );
seekp ( pos_type position );

Используя этот прототип, указатель потока изменяется, чтобы указывать на абсолютную позицию, рассчитанную с начала файла. Обязательные типы параметров такие же, как те, которые возвращаются функциями Tellg и Tellp.

seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );

Используя этот прототип, вы можете указать смещение от конкретного указателя, определяемого направлением параметра. может быть:

Значения указателей потока get и put рассчитываются по-разному для текстовых и двоичных файлов, поскольку некоторые специальные символы в файлах текстового режима могут быть изменены. По этой причине рекомендуется всегда использовать первые прототипы seekg и seekp для файлов, открытых в режиме текстовых файлов, и не изменять возвращаемое значение Tellg или Tellp. Для двоичных файлов вы можете использовать эти функции произвольно, и не должно быть неожиданного поведения.

В следующем примере эти функции используются для получения размера двоичного файла:

4. Двоичные файлы

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

Поток файлов включает в себя две функции-члена, специально предназначенные для последовательного чтения и записи данных: запись и чтение. Первая функция (запись) является функцией-членом ostream, которая наследуется от ofstream. И read является функцией-членом istream, унаследованной от ifstream. Объекты класса fstream имеют обе функции. Их прототип:

write ( char * buffer, streamsize size );
read ( char * buffer, streamsize size );

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

5. Буферы и синхронизация

Когда мы работаем с файловыми потоками, они связаны с буфером типа streambuf. Этот буфер (буфер) фактически является пространством памяти, как поток (поток) и носитель физического файла. Например, для выходного потока каждый раз, когда вызывается функция-член put (запись одного символа), этот символ не записывается напрямую в физический файл, соответствующий выходному потоку, но сначала вставляется в кэш потока ( буфер).

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

  • Когда файл закрыт:Перед закрытием файла все кэши, которые не были полностью записаны или прочитаны, будут синхронизированы.
  • Когда буфер кеша заполнен:Буферы имеют определенный предел пространства. Когда кеш заполнен, он будет автоматически синхронизирован.
  • Контрольный персонаж четко заявляет:Когда встречаются определенные управляющие символы в потоке, происходит синхронизация. Эти управляющие символы включают в себя: flush и endl.
  • Вызовите функцию sync () явно:Вызов функции-члена sync () (без параметров) может вызвать немедленную синхронизацию. Эта функция возвращает значение типа int, равное -1, указывающее, что поток не имеет кеша или операция не выполнена.

Интеллектуальная рекомендация

совместный запрос mysql с тремя таблицами (таблица сотрудников, таблица отделов, таблица зарплат)

1. Краткое изложение проблемы: (внизу есть инструкция по созданию таблицы, копирование можно непосредственно практиковать с помощью (mysql)) Найдите отделы, в которых есть хотя бы один сотрудник. Отоб.


[Загрузчик классов обучения JVM] Третий день пользовательского контента, связанного с загрузчиком классов


IP, сеанс и cookie

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