Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
програм.docx
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
241.8 Кб
Скачать

34.Бинарные файлы. Функции для работы с бинарными файлами.

C++ Двоичные файлы Сохранить динамическую структуру в бинарный файл

Внимание!

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

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

Я перерыл поиск вдоль и поперек, но не нашел ничего толкового по этому поводу. В основном был приведен пример, в котором используется статическая переменная.

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

Код C++ Сохранить/Прочитать динамическую структуру в бинарный файл

PHP1

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

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72 #include <iostream.h>

#include <fstream.h>

int n; //Число структур

char F[]="C:MyFile"; //Путь к файлу

//Некоторая структура

struct MyStruct

{

char Name[20];

int age;

};

MyStruct *X=0,*Y=0,*tempY; //Указатели на структуру

/*ФУНКЦИЯ ВВОДА ДАННЫХ В СТРУКТУРУ*/

void input(int i,MyStruct *X)

{

cout<<"ИМЯ ";

cin.getline(X[i].Name,20);

cout<<"ВОЗРАСТ ";

cin>>X[i].age;

cin.ignore();

cout<<"n";

}

/*ФУНКЦИЯ ВЫВОДА ДАННЫХ СТРУКТУРЫ НА ЭКРАН*/

void output(int i,MyStruct *X)

{

cout<<X[i].Name<<" "<<X[i].age<<endl;

}

//===============

void main()

{

n=5; //Пусть число структур 5

X=new MyStruct [n]; //Выделяем память под пять структур для указателя X

for (int i=0;i<n;i++) input(i,X); //Вводим n структур по типу структуры Х

for (i=0;i<n;i++) output(i,X); //Выводим n структур типа X на экран

ofstream create(F,ios::binary); create.close(); //Это я для себя переписывал файл

/*ЗАПИСЫВАЕМ ВСЮ СТРУКТУРУ В БИНАРНЫЙ ФАЙЛ*/

ofstream out(F,ios::binary|ios::out); //Открыли файл для записи в бинарном режиме

out.write((char*)&X,sizeof X); //Записали в файл структуру X

out.close(); //Закрыли открытый файл

/*ЧИТАЕМ СТРУКТУРЫ ИЗ БИНАРНОГО ФАЙЛА*/

tempY=0;int count=0; //Инициализируем указатель на структуру и счетчик в нули

ifstream in(F,ios::binary|ios::in); //Открыли бинарный файл для чтения

in.read((char*)&tempY,sizeof tempY); //Считываем первый блок

while (in.cur!=in.eof())

{

in.read((char*)&tempY,sizeof tempY); //Считываем все блоки файла

count++;

}

cout<<count<<endl;

in.close(); //Закрываем файл

Y=new MyStruct [count]; //Выделяем память для новых структур

for (int i=0;i<n;i++) Y[i]=tempY[i]; //Переселяем ячейки

for (int i=0;i<n;i++) cout<<Y[i].Name<<" "<<Y[i].age<<endl; //Выводим все структуры на экран

// Освобождаем память

delete tempY[];

delete[]Y;

delete []X;

}

Если вас интересует эта тема, то значит вы должны быть уже хорошо знакомы с общим представлением и созданием простых программ. Я постараюсь сделать акцент именно на нужную часть, чтобы всё получилось покомпактнее.

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

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

После того как написали стандартные и нужные функции, нужно записать данные файл. Если вы уже записывали файлы в бинарные файлы, то заметите, что в нашем случае нам не нужен цикл. Дело в том, что мы выделили память для структуры X и тем самым увеличили её размер.

PHP1

2 MyStruct *X //sizeof X = a;

X=new MyStruct [n]; //sizeof X=a*n;

Другими словами. Записать динамическую структуру в файл можно точно также как записать обычную переменную.

С записью в бинарный файл разобрались. Оказывается это не так сложно, но возникает вопрос по прочтению. Как прочитать из бинарного файла несколько структур.

Во избежание ошибок, указатель в который будем считывать структуры нужно инициализировать нулем. (или пустотой). При этом мы не обязательно знаем сколько структур в файл записано, значит хотим мы или нет, количество структур в бинарном файле придется посчитать. Инициализируем счетчик нулем. Теперь читаем данные из бинарника. Так как память под tempY не выделялась, то получается, что мы читаем данные из файла блоками, равными размеру структуры. Сколько таких блоков в файле мы не знаем и поэтому я использовал цикл с условием: “До тех пор пока курсор не встанет на позицию конца файла считывать информацию”. А с каждым новым прочтением блока, каждый прочитанный блок Дописывается в одну большую кучу, на начало которой указывает указатель TempY

Теперь, после того как мы считали всё в одну кучу, всю эту кучу данных по указателю TempY можно вывести на экран, используя счетчик count и цикл for . Кто-то может успокоиться и решить, что это все, что больше ничего не нужно. Но кто так подумает, тот совершит глобальную ошибку. Если вы вспомните, то увидите, что под TempY изначально не выделялось памяти, а значит любые полученные данные могут быть изгнаны из своих ячеек как нелегальные поселенцы. Такое выселение данных из ячеек может привести к непредсказуемым последствиям и поэтом всех надо переселить туда, откуда их ничто не выгонит. Для этого и использован третий указатель. Число структур известно и посчитано, значит выделяем под третий указатель столько памяти, сколько требуется и с помощью цикла переселяем данные динамических структур из небезопасной ячейки в безопасную

Мою идею легко довести до ума если уметь использовать динамические списки и в таком случае получите безопасное чтение структур из файла за один раз.