Форум программистов, компьютерный форум CyberForum.ru

Бинарные чтение/запись объектов - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
moskitos80
 Аватар для moskitos80
43 / 43 / 3
Регистрация: 04.10.2011
Сообщений: 142
Завершенные тесты: 1
13.08.2012, 17:33     Бинарные чтение/запись объектов #1
Всем привет. Люди добрые - поможите пожалуйста Написал такой код:
C++
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
44
45
46
47
48
49
50
51
#include <iostream>
#include <fstream>
#include <iomanip>
 
using namespace std;
 
/////////////////////////////////////////////////////////////////////////////////
class Person {
    public :
        void setData(void)
        {
            cout << endl << "Enter name . . . "; cin >> this->name;
            cout << endl << "Enter age . . . ";  cin >> this->age;
        }
        void showData(void)
        {
            cout << "Name " << this->name << endl
                 << "Age  " << this->age  << endl;
        }
    protected :
        int age;
        char name[80];
};
/////////////////////////////////////////////////////////////////////////////////
 
int main()
{
    fstream file;
    file.open("PERSON.DAT", ios::in|ios::out|ios::app|ios::binary);
 
    Person pers;
    char choice;
    
    do {
        pers.setData();
        file.write(reinterpret_cast<char*>(&pers), sizeof(pers));
        cout << endl << "Enter more ? (y/n) . . . "; cin >> choice;
    } while (choice != 'n');
 
    file.seekp(ios::beg);
    
    cout << endl << "RESULT: " << endl << endl;
 
    while (!file.eof()) {
        file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
        pers.showData();
        cout << setw(80) << setfill('-') << "" << endl;
    }
 
    return 0;
}
Он просто создаёт файл "PERSON.DAT" в директории, в которой он находится, а потом запрашивает данные у пользователя, и записывает объекты (или наверное правильнее "снимки" объектов) в этот файл. А затем из этого же файла читает данные и выводит в консоль. Беда в том, что последнюю запись он считывает 2 раза!

Никак не пойму в чём дело. Пытался открывать получающийся бинарник - очень похоже, что записи там каждая в одном экземпляре, а последняя почему-то выводится дважды... Подскажите пожалуйста, где я напортачил?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.08.2012, 17:33     Бинарные чтение/запись объектов
Посмотрите здесь:

запись и чтение динамических объектов в файл C++
Бинарные файлы, чтение и запись C++
Запись объектов в файл и чтение C++
Запись, чтение объектов в файл через указатели. C++
Запись и чтение объектов разных классов в один файл C++
fwrite\fread: чтение и запись в бинарные файлы C++
C++ Запись в бинарные файлы
Бинарные запись и чтение структуры в файл C++
Бинарные файлы. Чтение C++
Запись массивов в бинарные файлы C++
C++ Сериализация объектов с полями std::string + запись/чтение в файл
C++ Запись и чтение объектов класса в файл С ++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Invader_Zim
Twilight Parasite
 Аватар для Invader_Zim
153 / 149 / 2
Регистрация: 21.07.2011
Сообщений: 907
13.08.2012, 18:18     Бинарные чтение/запись объектов #2
moskitos80, для проверки сделай записи в файл последовательного доступа.

C++
1
2
3
4
5
    while (!file.eof()) {
        file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
        pers.showData();
        cout << setw(80) << setfill('-') << "" << endl;
    }
попробуй цикл do-while
moskitos80
 Аватар для moskitos80
43 / 43 / 3
Регистрация: 04.10.2011
Сообщений: 142
Завершенные тесты: 1
13.08.2012, 19:12  [ТС]     Бинарные чтение/запись объектов #3
Invader_Zim В файле чётко 3 объекта: файл вЕсит 252 байта. Так что с записью всё ок. Попробовал выводить так Вы посоветовали:
C++
1
2
3
4
5
   do {
        file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
        pers.showData();
        cout << setw(80) << setfill('-') << "" << endl;
    } while (!file.eof());
Увы - не помогло. Эх...

Добавлено через 16 минут
Добавил проверку:
C++
1
2
3
4
5
6
7
8
9
10
11
    do {
        file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
 
        if (!file) {
            cerr << "Error: can`t read from file";
            return 1;
        }
 
        pers.showData();
        cout << setw(80) << setfill('-') << "" << endl;
    } while (file);
Теперь вместо дубля последней записи (в конце) выдаёт ошибку: Error: can`t read from file
Всё-равно непойму что твориться...

Добавлено через 27 минут
Разобрался сам, добавив такую проверку:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    do {
        file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
 
        if (file.eof()) {
            cerr << "End of file ";
            return 1;
        } else if (file.fail()) {
            cerr << "Fail bit ";
            return 1;
        } else if (file.bad()) {
            cerr << "Bad bit ";
            return 1;
        }
 
        pers.showData();
        cout << setw(80) << setfill('-') << "" << endl;
    } while (file);
Понял, что EOF подкрался незаметно а на экран: pers.showData() самый последний раз выводится остаточное значение pers поэтому получается, что последняя запись выводится 2 раза. Проверку на конец файла нужно производить после операции чтения, вот листинг который работает правильно (если кому интересно):

C++
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <fstream>
#include <iomanip>
#include "process.h"
using namespace std;
 
/////////////////////////////////////////////////////////////////////////////////
class Person {
    public :
        void setData(void)
        {
            cout << endl << "Enter name . . . "; cin >> this->name;
            cout << endl << "Enter age . . . ";  cin >> this->age;
        }
        void showData(void)
        {
            cout << "Name " << this->name << endl
                 << "Age  " << this->age  << endl;
        }
    protected :
        int age;
        char name[80];
};
/////////////////////////////////////////////////////////////////////////////////
 
const char* FILE_NAME = "C:\\PERSON.DAT";
 
int main()
{
    fstream file;
 
 
    file.open(FILE_NAME, ios::in|ios::out|ios::app|ios::binary);
 
    if (!file) {
        cerr << "Error: can`t open file " << FILE_NAME;
        return 1;
    }
 
    Person pers;
    char choice;
 
    do {
        pers.setData();
        file.write(reinterpret_cast<char*>(&pers), sizeof(pers));
 
        if (!file) {
            cerr << "Error: can`t write in file " << FILE_NAME;
            return 1;
        }
 
        cout << endl << "Enter more ? (y/n) . . . "; cin >> choice;
    } while (choice != 'n');
 
    file.seekp(ios::beg);
    cout << endl << "RESULT: " << endl << endl;
 
    file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
 
    while (!file.eof()) {
        pers.showData();
        cout << setw(80) << setfill('-') << "" << endl;
        file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
    }
 
    return 0;
}
Можно закрыть тему.
Yandex
Объявления
13.08.2012, 19:12     Бинарные чтение/запись объектов
Ответ Создать тему
Опции темы

Текущее время: 01:32. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru