109.95K
Категория: ПрограммированиеПрограммирование

Работа с двоичными файлами

1.

Работа с
двоичными
файлами

2.

Двоичные (бинарные) файлы
Двоичные файлы хранят данные в виде набора
байт. Работа с двоичными файлами не похожа на
работу с текстовыми (<< и >> не используются)
Здесь также используются классы ifstream и
ofstream из библиотеки <fstream>
Для работы с файлом в двоичном режиме нужно
указать флаг ios::binary

3.

Режимы открытия файлов
• ifstream fin(nameF, ios::in | ios::binary);
• ofstream fout(nameF,ios::app |ios::binary);
• fstream finout(nameF, ios::in | ios::out | ios::binary);

4.

Запись строки в двоичный файл
• Для записи в двоичный файл используется метод write,
принимающий указатель на массив байт (char*) и количество
записываемых байт. Пример записи строки:
string s = "Hello, world!";
ofstream file("text.dat", ios::binary);
if (file.is_open()) {
file.write(s.c_str(), s.length() + 1);
file.close();
}

5.

Чтение строки из двоичного файла
• Для чтения из двоичного файла используется read,
принимающий указатель на массив байт (char*) и количество
считываемых байт. Пример чтения строки:
ifstream file("text.dat", ios::binary);
if (file.is_open()) {
char s[15];
file.read(s, 15);
cout << s;
}

6.

Запись в двоичные файлы
• Для записи нестроковых данных в двоичные файлы их
необходимо интерпретировать как массив байт. Для этого
используется преобразование reinterpret_cast
int a = 5;
char* data = reinterpret_cast<char*>(&a);
Теперь data - указатель на массив четырех байт, в
котором записано число 5

7.

Запись в двоичные файлы
Пример записи массива целых чисел
int arr[5] = { 1, 2, 3, 4, 5 };
ofstream file("text.dat", ios::binary);
if (file.is_open()) {
for (int i = 0; i < 5; i++) {
file.write(reinterpret_cast<char*>(&arr[i]),
sizeof(int));
}
file.close();
}

8.

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

9.

Запись в двоичные файлы
Теперь при каждом запуске данные будут
дописываться в конец
int arr[5] = { 1, 2, 3, 4, 5 };
ofstream file("text.dat", ios::binary | ios::app);
if (file.is_open()) {
for (int i = 0; i < 5; i++) {
file.write(reinterpret_cast<char*>(&arr[i]),
sizeof(int));
}
file.close();
}

10.

Файловый указатель для чтения
Пример. Дан бинарный файл, содержащий целые
числа типа int. Считать все числа
ifstream file("text.dat", ios::binary);
int value;
if (file.is_open()) {
while (!file.eof()) {
file.read(reinterpret_cast<char*>(&value),
sizeof(int));
cout << value << " ";
}
}

11.

Файловый указатель для чтения
Пример. Дан бинарный файл, содержащий целые
числа типа int. Считать все числа (вариант 2)

12.

Файловый указатель
• В отличие от текстового режима, в бинарном режиме можно
управлять, куда записывать и откуда считывать.
• Бинарный режим предоставляет произвольный доступ к
данным (можно сразу обратиться к любому байту, не считывая
предыдущие)
• Такое управление осуществляется через файловый
указатель

13.

Файловый указатель для чтения
Пусть file - бинарный файл ifstream
● file.is_open() - проверяет, был ли файл успешно открыт.
Возвращает true/false
● file.close() - закрывает файл
● file.eof() - проверить, был ли достигнут конец файла
● file.get() - считать один байт
● file.peek() - получить следующий байт (но не считывать его)
● file.tellg() - получает текущую позицию указателя
● file.seekg(pos) - перемещает файловый указатель
● file.seekg(offset, origin) - перемещает файловый указатель
относительно позиции origin

14.

Файловый указатель для чтения
seekg(0, ios::end) - перейти к концу файла
seekg(-4, ios::cur) - сместиться на 4 байта влево от
текущего значения
seekg(8, ios::beg) - перейти на 8-ой байт с начала
файла
seekg(-4, ios::end) - перейти на 4-ой байт с конца
файла

15.

Файловый указатель для чтения
Пример. Дан бинарный файл, содержащий целые
числа типа int. Считать последнее число
file.open("text.dat", ios::binary);
int intSize = sizeof(int);
if (file.is_open()) {
file.seekg(-intSize, ios::end);
int value;
file.read(reinterpret_cast<char*>(&value), intSize);
cout << value << " ";
file.close();
}

16.

Файловый указатель для записи
Пусть file - бинарный файл ofstream
● file.is_open() - проверяет, был ли файл успешно открыт.
Возвращает true/false
● file.close() - закрывает файл
● file.tellp() - получает текущую позицию указателя
● file.seekp(pos) - перемещает файловый указатель
● file.seekp(offset, origin) - перемещает файловый указатель
относительно позиции origin

17.

Файловый указатель для записи
Пример. Дан бинарный файл, содержащий целые
числа типа int. Заменить пятое число на 255
ofstream file("text.dat", ios::binary | ios::ate | ios::in);
int intSize = sizeof(int);
int value = 255;
if (file.is_open()) {
file.seekp(4 * intSize, ios::beg);
file.write(reinterpret_cast<char*>(&value), sizeof(int));
file.close();
}

18.

Запись в двоичные файлы
• Режим ios::app не позволяет двигать файловый указатель.
Единственный способ открыть файл без перезаписи и
сохранить произвольный доступ - режим ios::ate (at the end).
Он также устанавливает указатель на конец файла при открытии.
Но такой режим подразумевает, что мы будем читать данные,
поэтому работает только вместе с режимом ios::in

19.

Чтение и запись в двоичные файлы
Иногда требуется одновременно читать из файла и
писать в него. Для этого существует тип fstream,
который включает в себя возможности и функции из
ifstream и ofstream. Для такого файла создаются 2
файловых указателя: “читающий” и “пишущий”
Для fstream требуется явно указывать, хотим ли мы
читать файл или записывать в него

20.

Чтение и запись в двоичные файлы
Открытие файла сразу на чтение и запись:
fstream file("text.dat", ios::binary | ios::in | ios::ate | ios::out);
Описание указанных режимов:
● ios::ate | ios::out - открыть на запись без перезаписи
● ios::in - открыть на чтение
● ios::binary - открыть в бинарном режиме

21.

Чтение и запись в двоичные файлы
• Пример: дан двоичный файл, содержащий целые числа типа int.
Считать первое число и заменить им последнее число
fstream file("text.dat", ios::binary | ios::in |
ios::ate | ios::out);
• int intSize = sizeof(int); int value;
if (file.is_open()) {
file.seekg(0);
• file.read(reinterpret_cast<char*>(&value), intSize);
• file.seekp(-intSize, ios::end);
file.write(reinterpret_cast<char*>(&value), intSize);
file.close();
• }

22.

Запись структур в двоичный файл
Преимущество двоичного режима - можно свободно
записывать сложные типы, например, структуры. C++
сам разберется, как именно записать данные
Рассмотрим примеры со структурой точки Point
struct Point {
double x, y;
};

23.

Запись структур в двоичный файл
Запись структуры в файл:
Point point; point.x = 2.5; point.y = 3.1415;
ofstream file("text.dat", ios::binary);
if (file.is_open()) {
file.write(reinterpret_cast<char*>(&point),
sizeof(Point));
file.close();
}

24.

Чтение структур из двоичного файла
Чтение структуры из файла:
Point point;
ifstream file("text.dat", ios::binary);
if (file.is_open()) {
file.read(reinterpret_cast<char*>(&point),
sizeof(Point));
cout << point.x << " " << point.y;
file.close();
}
English     Русский Правила