Работа с файлами с использованием конструкций языка Си была рассмотрена здесь.
Для программиста открытый файл представляется как последовательность считываемых или записываемых данных. При открытии файла с ним связывается поток ввода-вывода. Выводимая информация записывается в поток, вводимая информация считывается из потока.
Для работы с файлами необходимо подключить заголовочный файл <fstream>. В нем определены несколько классов и подключены заголовочные файлы
- <ifstream> — файловый ввод ;
- <ofstream> — файловый вывод.
Файловый ввод-вывод аналогичен стандартному вводу-выводу, единственное отличие – это то, что ввод-вывод выполнятся не на экран, а в файл.
Если ввод-вывод на стандартные устройства выполняется с помощью объектов cin и cout, то для организации файлового ввода-вывода достаточно создать собственные объекты, которые можно использовать аналогично этим операторам.
При работе с файлом можно выделить следующие этапы:
- создать объект класса fstream (возможно, ofstream или ifstream);
- связать объект класса fstream с файлом, который будет использоваться для операций ввода-вывода;
- осуществить операции ввода-вывода в файл;
- закрыть файл.
2
3
4
5
6
7
8
9
10
#include <fstream>
using namespace std;
int main()
{
ofstream fout;
fout.open("file.txt");
fout << "Привет, мир!";
fout.close();
return 0;
}
В результате будет создан файл
Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе ios предусмотрены константы, которые определяют режим открытия файлов.
Константа | Описание |
ios::in | открыть файл для чтения |
ios::out | открыть файл для записи |
ios::ate | при открытии переместить указатель в конец файла |
ios::app | открыть файл для записи в конец файла |
ios::trunc | удалить содержимое файла, если он существует |
ios::binary | открытие файла в двоичном режиме |
Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове метода open().
Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции ИЛИ |, например:
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() — позиция для вывода
Пример на С++
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
char s[80];
fstream inOut;
inOut.open("file.txt", ios::out);
inOut << "строчка текста" << endl;
inOut.seekp(8, ios::beg);
inOut << "еще строчка текста";
inOut.close();
inOut.open("file.txt", ios::in);
inOut.seekg(-6, ios::end);
inOut >> s;
inOut.close();
cout << s;
cin.get();
return 0;
}
В результате выполнения первой части программы будет создан файл
Вторая часть программы выведет в консоль
Ещё один пример. Допустим, нам нужно заполнять таблицу
ФИО | Дата рождения | Хобби |
Причем каждая вновь введенная строка должна размещаться в таблице непосредственно под «шапкой».
Алгоритм решения задачи следующий:
- формируем очередную строку для вывода
- открываем файл для чтения, считываем из него данные и сохраняем их в массив строк
- закрываем файл
- открываем файл для записи
- выводим «шапку» таблицы
- выводим новую строку
- выводим все сохраненные строки обратно в файл, начиная со строки после шапки
Пример на C++
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
#include <iostream>
#include <fstream>
using namespace std;
#define LINES 100 // максимальное количество строк в файле
int main() {
system("chcp 1251");
system("cls");
char line[LINES][100];
char str[30];
char s[] = "| | | |";
// Ввод данных для размещаемой строки
cout << "ФИО: ";
cin.getline(str, 30); // вводим ФИО
for (int i = 0; str != '\0'; i++) // копируем в строку без 0
s[i + 2] = str[i]; // начиная с указанной позиции
cout << "Дата: ";
cin.getline(str,30);
for (int i = 0; str != '\0'; i++)
s[i + 33] = str[i];
cout << "Хобби: ";
cin.getline(str,30);
for (int i = 0; str != '\0'; i++)
s[i + 50] = str[i];
fstream inOut;
inOut.open("file.txt", ios::in); // открываем файл для ввода
// Считываем из файла имеющиеся данные
int count = 0;
while (inOut.getline(line[count], 100))
count++;
inOut.close(); // закрываем файл
inOut.open("file.txt", ios::out); // открываем файл для вывода
inOut << "--------------------------------------------------------------------------------" << endl;
inOut << "| ФИО | Дата | Хобби |" << endl;
inOut << "--------------------------------------------------------------------------------" << endl;
inOut << s << endl; // выводим сформированную строку
inOut << "--------------------------------------------------------------------------------" << endl;
// Выводим обратно в файл все строки кроме "шапки" (первые 3 строки)
for (int j = 3; j < count; j++)
{
inOut << line[j] << endl;
}
inOut.close();
cin.get();
return 0;
}
Результат выполнения: