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

Сохранение и чтение объекта класса в файл/из файла - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 38, средняя оценка - 4.61
Kos87
Сообщений: n/a
12.05.2012, 23:29     Сохранение и чтение объекта класса в файл/из файла #1
Добрый день!

Столкнулся с проблемой сохранения объекта класса в файл, и последующего его чтения.
Задача такая: имеем vector base, в котором есть объекты Person. Нужно писать из вектора в файл, а потом читать из файла в вектор.

В файл вроде все пишет. А вот при чтении вылазит ошибка (скрин ошибки прикреплен внизу).

Буду благодарен за помощь в решении моей проблемы. Может у меня подход не тот, или еще где тупонул ....

Также прикрепляю проект (VisualStudio 2010).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
// Base.h
#pragma once
#include "Header.h"
#include "Person.h"
 
class Base
{
public:
    Base(void);
    ~Base(void);
    static vector<Person> base;
    static bool successful_add; // контролирует был ли добавлен элемент в вектор
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Base.cpp
#include "Base.h"
 
vector<Person> Base::base;
bool Base::successful_add = false;
 
Base::Base(void)
{
}
 
 
Base::~Base(void)
{
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Person.h
#pragma once
#include "Header.h"
 
class Person
{
public:
    Person(void);
    ~Person(void);
    bool operator<(const Person&) const;
    
    wstring name, surname, phone, full_name;
    int age;
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Person.cpp
 
#include "Person.h"
 
Person::Person(void)
{
    age = 0;
}
 
Person::~Person(void)
{
}
 
bool Person::operator<(const Person& p) const
{
    return wcsicmp(full_name.c_str(), p.full_name.c_str()) < 0 ? true : false; // если первая строка меньше второй
}
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
void MainWindow::SaveToFile()
{
    /* пишем в бинарном режиме в файл целым классом как одним блоком */
    ofstream file("base.txt", ios::trunc|ios::binary); //
 
    for(int i=0; i<Base::base.size(); ++i)
    {
        file.write((char*) &Base::base[i], sizeof(Person));
    }
    file.close();
}
 
void MainWindow::LoadFromFile()
{
    ifstream file("base.txt", ios::binary);
    
    if(!file) // проверка - существует ли такой файл
        MessageBox(hDialog, L"File does not exist!", L"Error", MB_OK|MB_ICONERROR);
    else
    {
        /* чистим ListBox и Vector */
        SendMessage(hName_list, LB_RESETCONTENT, 0, 0);
        Base::base.clear();
 
        /* пишем в наш вектор с файла целым классом */
        while(!file.eof() && !file.fail())
        {
            Base::base.push_back(Person());
            file.read((char*) &Base::base.back(), sizeof(Person));
            
            /* выводим элемент в ListBox */
            ListBox_AddString(hName_list, Base::base.back().full_name.c_str());
        }
 
        file.close();
    }
}
Миниатюры
Сохранение и чтение объекта класса в файл/из файла  
Вложения
Тип файла: zip PersonalInfo.zip (1.11 Мб, 29 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.05.2012, 23:29     Сохранение и чтение объекта класса в файл/из файла
Посмотрите здесь:

C++ Чтение и сохранение данных из конфигурационного файла
C++ Вывод в файл и последующее чтение из файла объектов класса
C++ Чтение и сохранение JPEG файла
ООП. header файл. Функцию объекта вынести в файл класса C++
Сохранение класса в файл и его чтение C++
C++ Работа со структурой данных, чтение/сохранение во внешний файл
C++ Не работает метод класса (запись и чтение в файл)
C++ Сохранение и чтение структуры из файла (crash программы)

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
StudentDan
20 / 20 / 1
Регистрация: 13.05.2012
Сообщений: 27
13.05.2012, 06:36     Сохранение и чтение объекта класса в файл/из файла #2
Доброе утро!

Программа и пишет в файл неправильно и читает. Тип данных wstring содержит по умолчанию 8 символов. sizeof возвращает размер именно такой стандартной строки - 32. Правильно работает эта функция только для массивов. Однако для строки длиной больше 7 символов потребуется больше памяти.
Также sizeof(Person) и sizeof(Base::base[i]) всегда совпадают и равны 132. Если считать сумму sizeof полей Base::base[i] мы тоже получим 132. Поэтому вывод в файл одной записи, даже отдельно по полям, всегда содержит 132 байта, что меньше реального размера, если name/surname/full_name больше 7 символов. Считывается же из файла также блок из 132 символов. И получается, что, к примеру, в заголовке full_name прописано capacity=15, а считывается меньше. Получаем неправильный указатель и компилятор ругается на это.

Можно сначала выводить длину строки, а затем саму строку посимвольно (я не знаю истинного размера строки). Рабочим вариантом записи поля name в файл будет
C++
1
2
3
4
5
 int Len = Base::base[i].name.size();
 file.write((char*) &Len, sizeof(Len));
 
 for (int j = 0; j < Len; j++)
  file.write((char*) &Base::base[i].name[j], 2);
А считывание тогда имеет вид
C++
1
2
3
4
5
6
7
8
9
10
11
 int Len;
 file.read((char*) &Len, sizeof(Len));
 
 wstring Str=L"";
 wchar_t ch;
 
 for (int I = 0; I < Len; I++)
 {
  file.read((char*) &ch, 2);
  Str = Str + ch;
 }
И так для каждого поля Person, или написать функции ввода/вывода.

Ещё у тебя в конце лишний раз считывается последняя буква как отдельное слово.

При неправильном вводе данных в форме добавления в справочник, кнопка OK больше не загорается.
Kos87
Сообщений: n/a
22.05.2012, 12:40     Сохранение и чтение объекта класса в файл/из файла #3
Проблема решилась. Суть в том чтобы читать по "стрингам" с файла, и писать в него также, используя пробелы как разделители. Вот правильный код:
Также прикрепляю готовый проект (Visual Studio 2010).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
// Base.h
#pragma once
#include "Header.h"
#include "Person.h"
 
class Base
{
public:
    Base(void);
    ~Base(void);
    static vector<Person> base;
    static bool successful_add; // контролирует был ли добавлен элемент в вектор
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
// Base.cpp
#include "Base.h"
 
vector<Person> Base::base;
bool Base::successful_add = false;
 
Base::Base(void)
{
}
 
Base::~Base(void)
{
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Person.h
#pragma once
#include "Header.h"
 
class Person
{
public:
    Person(void);
    ~Person(void);
    bool operator<(const Person&) const;
    
    wstring name, surname, phone, full_name, lower_name, lower_surname;
    int age;
private:
    friend wofstream& operator<<(wofstream& out, const Person &p);
    friend wifstream& operator>>(wifstream& in, Person &p);
};
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
// Person.cpp
#include "Person.h"
 
Person::Person(void)
{
    age = 0;
}
 
Person::~Person(void)
{
}
 
bool Person::operator<(const Person& p) const
{
    return wcsicmp(full_name.c_str(), p.full_name.c_str()) < 0 ? true : false; // если первая строка меньше второй
}
 
wofstream& operator<<(wofstream& out, const Person &p)
{
    out<<p.surname<<L' '<<p.name<<L' '<<p.age<<L' '<<p.phone<<L'\n';
 
    return out;
}
 
wifstream& operator>>(wifstream& in, Person &p)
{
    in>>p.surname;
    in.get();
    in>>p.name;
    in.get(); // убираем один символ, в нашем случае пробел
    in>>p.age;
    in.get();
    in>>p.phone;
    in.get(); // забираем символ конца строки
 
    p.full_name = p.surname + L' '+ p.name;
    
    /* преобразовываем строки для поиска */
    for(int i=0; i<p.name.size(); ++i)
        p.lower_name.push_back( tolower(p.name[i]) );
 
    for(int i=0; i<p.surname.size(); ++i)
        p.lower_surname.push_back( tolower(p.surname[i]) );
 
    return in;
}
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
void MainWindow::SaveToFile()
{
    /* пишем в файл целым классом как одним блоком */
    wofstream out("base.txt", ios::trunc);
 
    for(int i=0; i<Base::base.size(); ++i)
        out<<Base::base[i];
 
    out.close();
}
 
void MainWindow::LoadFromFile()
{
    wifstream in("base.txt");
    
    if(!in) // проверка - существует ли такой файл
        MessageBox(hDialog, L"File does not exist!", L"Error", MB_OK|MB_ICONERROR);
    else
    {
        /* чистим ListBox и Vector */
        SendMessage(hName_list, LB_RESETCONTENT, 0, 0);
        Base::base.clear();
        
        /* пишем в наш вектор с файла целым классом */
        char ch;
        while(true)
        {
            ch = in.get();
            if(in.eof() || in.fail()) break;
            in.putback(ch);
 
            Base::base.push_back(Person());
            in>>Base::base.back();
 
            /* выводим элемент в ListBox */
            ListBox_AddString(hName_list, Base::base.back().full_name.c_str());
        }
 
        in.close();
    }
}
Вложения
Тип файла: zip 15_dz_PersonalInfo.zip (2.17 Мб, 89 просмотров)
Yandex
Объявления
22.05.2012, 12:40     Сохранение и чтение объекта класса в файл/из файла
Ответ Создать тему
Опции темы

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