При программировании в реальном времени мы имеем дело с большими блоками данных, которые невозможно разместить на стандартных устройствах ввода-вывода. Следовательно, нам нужно использовать вторичное хранилище для хранения данных. Во вторичном хранилище, данные обычно хранятся данные в виде файлов.
Мы можем читать данные из файлов или записывать данные в файлы, используя последовательность данных, называемую потоками, в текстовом или двоичном формате. Существуют различные операции ввода/вывода и другие операции, связанные с файлами в C++. В этой статье объясняются эти операции, связанные с файлами, с использованием различных классов.
Классы файлового ввода/вывода в C++
Мы рассказывали про класс iostream в C++, который определяет стандартные функции ввода и вывода, включая cin и cout. Этот класс ограничен стандартными устройствами ввода и вывода, такими как клавиатура и монитор соответственно.
Когда дело доходит до операций с файлами, в C++ есть набор классов, который можно использовать.
Эти классы описаны ниже:
- Ofstream: класс обработки файлов, который обозначает выходной файловый поток и используется для записи данных в файлы.
- Ifstream: класс обработки файлов, который обозначает входной файловый поток и используется для чтения данных из файла.
- Fstream: класс обработки файлов, который может обрабатывать как ifstream, так и ofstream. Его можно использовать для чтения и записи в файл.
В C++ обработку файлов поддерживают следующие операции:
- Открытие файла
- Закрытие файла
- Чтение из файла
- Запись в файл
Давайте рассмотрим каждую из этих операций в деталях.
Открытие файла
Связывание объекта одного из потоковых классов с файлом либо для чтения, либо для записи, либо для того и другого называется открытием файла. Открытый файл представлен в коде с помощью этого объекта потока. Таким образом, любая операция чтения/записи, выполняемая с этим потоковым объектом, будет применяться и к физическому файлу.
Общий синтаксис для открытия файла с потоком:
1 |
void open(const char* filename, ios::open mode mode) |
filename => строка, содержащая путь и имя открываемого файла.
mode => необязательный параметр, указывающий режим, в котором файл должен быть открыт.
C++ поддерживает различные режимы открытия файла. Мы также можем указать комбинацию этих режимов с помощью оператора OR.
Файловый режим | Описание |
ios::in | Открывает файл в режиме ввода для чтения. |
ios::out | Открывает файл в режиме вывода для записи данных в файл. |
ios::ate | Устанавливает начальную позицию в конце файла. Если флаг конца файла не установлен, начальное положение устанавливается в начало файла. |
ios::trunc | Если файл открыт для записи и уже содержит содержимое, оно усекается. |
ios::app | Открывает файл в режиме добавления, так что все содержимое добавляется в конец файла. |
ios::binary | Открывает файл в бинарном режиме. |
Например, если мы хотим открыть файл «myfile.dat» для добавления данных в двоичном режиме, мы можем написать следующий код:
1 |
ofstream myfile; |
1 |
myfile.open(“myfile.dat”, ios::out|ios::app|ios::binary); |
Как уже упоминалось, параметр режима является необязательным. Когда мы открываем файл без указания второго параметра, открытая функция-член ofstream, ifstream или fstream имеет режим по умолчанию для открытия файла.
Они представлены следующим образом:
Класс | Режим по умолчанию |
Ifstream | ios::in |
ofstream | ios::out |
Fstream | ios::in|ios::out |
Итак, если мы не указываем второй параметр в функции открытия, в зависимости от используемого класса потока файл открывается в режиме по умолчанию.
Закрытие файла
Мы можем использовать функцию закрытия, чтобы закрыть файл и освободить ресурсы, удерживаемые файлом, когда мы закончим операции ввода и вывода в файле.
Функция закрытия файла:
1 |
void close() |
Итак, когда мы закончим операции с вышеуказанным файлом myfile, мы можем закрыть файл следующим образом:
1 |
myfile.close(); |
Как только файл закрыт с помощью функции закрытия, связанный файловый объект может быть повторно использован для открытия другого файла.
Чтение из файла
Мы можем прочитать информацию из файла построчно, используя оператор извлечения потока (>>). Это похоже на чтение ввода со стандартного ввода с помощью cin. Единственная разница в том, что в случае файлов мы используем объект ifstream или fstream вместо cin.
Пример кода для чтения из файла приведен ниже:
1 2 3 4 5 |
ifstream myfile; myfile.open(“samp_file.txt”); cout<<”Reading from a file”<<endl; myfile>>data; cout<<data<<endl; myfile.close(); |
В приведенном выше коде мы открываем файл и с помощью оператора извлечения потока (>>) читаем содержимое файла. Закончив чтение, мы можем закрыть файл.
Запись в файл
Мы также можем записывать данные в файл, используя файловые операции. Оператор, который мы используем для записи данных в файл, — это оператор вставки потока (<<). Опять же, это тот же самый оператор, который мы используем для вывода данных на стандартное устройство вывода с помощью cout. Разница между ними заключается в том, что для записи, связанной с файлом, мы используем объект ofstream или fstream.
Давайте рассмотрим следующий пример кода:
1 2 3 4 5 6 7 |
char data[100]; ofstream myfile; myfile.open(“samp_file.txt”); cout<<”Enter the string to be written to file”<<endl; cin.getline(data, 100); myfile<<data<<endl; myfile.close(); |
Здесь мы читаем строку из ввода и записываем ее в файл, который был открыт с помощью объекта ofstream.
В приведенном ниже примере кода продемонстрированы все операции по обработке файлов:
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 |
#include <fstream> #include <iostream> using namespace std; int main () { char data[100]; // opening a file in write mode. ofstream myfile; myfile.open("E:\\message.txt"); cout << "Writing to the file" << endl; cout << "Enter your name: "; cin.getline(data, 100); myfile << data << endl; cout << "Enter your age: "; cin >> data; cin.ignore(); myfile << data << endl; // close the opened file. myfile.close(); // opening a file in read mode. ifstream infile; infile.open("E:\\message.txt"); cout << "Reading from a file" << endl; infile >> data; cout << data << endl; infile >> data; cout << data << endl; infile.close(); return 0; } |
Вывод данных:
1 2 3 4 5 6 |
Writing to the file Enter your name: Alex Enter your age: 7 Reading from a file Alex 7 |
В приведенной выше программе сначала мы открываем файл в режиме записи. Затем мы читаем данные, т.е. имя и возраст, и записываем их в файл. Затем мы закрываем этот файл. Далее открываем этот же файл в режиме чтения и считываем данные построчно из файла и выводим на экран.
Таким образом, эта программа охватывает все операции файлового ввода-вывода.
Проверка состояния файла
Есть несколько функций-членов, которые используются для проверки состояния файла. Все эти функции возвращают логическое значение.
Мы свели в таблицу эти функции следующим образом:
Функция | Описание |
eof() | Возвращает true, если при чтении файла достигнут конец файла. |
fail() | Возвращает true при сбое операции чтения/записи или возникновении ошибки формата |
bad() | Возвращает true, если чтение или запись в файл завершились неудачно. |
good() | Возвращает false в тех же случаях, когда вызов любой из вышеперечисленных функций вернул бы true. |
Get/Put и другие специальные операции
Потоки файлового ввода-вывода, которые вы видели до сих пор, имеют внутренние позиции get и put, аналогичные другим потокам ввода-вывода, таким как iostream.
Класс ifstream имеет внутреннюю позицию получения, которая содержит расположение элемента/символа, который будет считан в файле при следующей операции ввода. Класс ofstream имеет внутреннюю позицию ввода, которая содержит расположение элемента/символа, который будет записан в следующей операции вывода.
Между прочим, у fstream есть позиции get и put.
Чтобы облегчить чтение и запись с использованием этих позиций, у нас есть несколько функций-членов, которые используются для изменения этих позиций.
Эти функции перечислены ниже:
Функции | Описание |
tellg() | Возвращает текущую позицию указателя get |
tellp() | Возвращает текущую позицию указателя ввода |
seekg(position) | Перемещение получает указатель на указанное место, отсчитывая от начала файла |
seekg(offset,direction) | Перемещение получает указатель на значение смещения относительно точки, заданной параметром direction. |
seekp(position) | Перемещает указатель на указанное место, отсчитывая от начала файла |
seekp(offset, direction) | Перемещение помещает указатель на значение смещения относительно точки, заданной параметром direction. |
Направление параметра, данное в приведенных выше прототипах функций, является перечисляемым типом типа seekdir и определяет точку, от которой отсчитывается смещение.
Оно может иметь следующие значения:
ios::beg | Смещение от начала потока |
ios::cur | Смещение от текущей позиции |
ios::end | Смещение от конца потока |
Давайте посмотрим на полный пример, демонстрирующий использование этих функций:
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 |
#include <iostream> #include <fstream> using namespace std; int main() { fstream myfile; myfile.open("E:\\myfile.txt",ios::out); if(!myfile) { cout<<"Cannot create File..."; } else { cout<<"New file created"<<endl; myfile<<"This is file input output tutorial"; cout<<"Initial File Pointer Position at: "<<myfile.tellp()<<endl; myfile.seekp(-1, ios::cur); cout<<"After seekp(-1, ios::cur), File Pointer Position at: "<<myfile.tellp()<<endl; myfile.close(); } myfile.open("E:\\myfile.txt",ios::in); if(!myfile) { cout<<"Cannot open File...No such file"; } else { char ch; myfile.seekg(5, ios::beg); cout<<"After seekg(5, ios::beg), File Pointer at: "<<myfile.tellg()<<endl; cout<<endl; myfile.seekg(1, ios::cur); cout<<"After seekg(1, ios::cur), File Pointer at: "<<myfile.tellg()<<endl; myfile.close(); } return 0; } |
Вывод данных:
1 2 3 4 5 6 7 8 9 |
New file created Initial File Pointer Position at: 34 After seekp(-1, ios::cur),File Pointer Position at: 33 After seekg(5, ios::beg), File Pointer at: 5 After seekg(1, ios::cur), File Pointer at: 6 |
Как показано в приведенной выше программе, у нас есть созданный файл, в который мы записываем строку текста. Затем, используя различные функции, описанные выше, мы отображаем различные положения указателя файла.
Итог
В этой статье мы рассмотрели различные операции с файлами для открытия, закрытия и чтения/записи данных из/в файл.
Мы также привели функции для изменения указателя файла для доступа к определенным позициям в файле. В следующей статье мы поговорим об обработке исключений в C++ для повышения надежности и эффективности кода.
С Уважением, МониторБанк