Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13

Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна

08.09.2014, 01:40. Показов 1853. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется задачка:
Написать программу которая будет записывать бинарные данные в файл, а так-же строковые данные типа std::string, считывать их обратно. Функции write() и read()

решил вот так..
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
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
 
struct person {
    std::string name; //имя
    int age;          //возраст
    double height;    //рост
};
const char *file = "d://person.max";
 
int main() {
    setlocale(0, "");
    person ps;
    std::ifstream fin;
    std::ofstream fout;
        //показывает содержимое файла при старте
    fin.open(file, std::ios_base::in | std::ios_base::binary);
    if (fin.is_open()) {
        std::cout << "Данные в файле \"person.max\":\n";
        unsigned int kol = 0;
        while (fin.read((char *)&ps, sizeof(ps))) {
            std::cout << kol + 1 << ") " << ps.name 
                << ", возраст " << ps.age 
                << ", рост " << ps.height << '\n';
            kol++;
        }
        fin.close();
    }
    //добавление данных в файл
    fout.open(file, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
    if (!fout.is_open()) {
        std::cerr << "ERROR\n";
        exit(EXIT_FAILURE);
    }
    std::cout << "Введите имя (пустая строка для выхода):\n";
    int i = 0;
    std::getline(std::cin, ps.name);
    while (ps.name.size() > 0) {
        std::cout << "Введите возраст: ";
        std::cin >> ps.age;
        std::cout << "Введите рост: ";
        std::cin >> ps.height;
        fout.write((char *)&ps, sizeof(ps));
        std::cout << "Введите имя (пустая строка для выхода):\n";
        i++;
        std::getline(std::cin, ps.name);
    }
    fout.close();
        //показывает модифицированный файл
    fin.open(file, std::ios_base::in | std::ios_base::binary);
    if (fin.is_open()) {
        std::cout << "Новые данные в файле:\n";
        unsigned int kol = 0;
        while (fin.read((char *)&ps, sizeof(ps))) {
            std::cout << kol + 1 << ") " << ps.name 
                << ", возраст " << ps.age << 
                ", рост " << ps.height << '\n';
            kol++;
        }
        fin.close();
    }
    system("pause");
    return 0;
}
Проблема в том, что программа вроде и работает, а вроде и нет.. Крашится при закрытии консольного окна.. может кто чем просветит?
Спасибо.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.09.2014, 01:40
Ответы с готовыми решениями:

Создание бинарных файлов. Чтение и запись бинарных файлов
Здраствуйте. Сколько я не рылся в нете сколько не искал, как то все не доходит до меня тупого). На работе есть задание: 1. есть данные...

Запись и чтение бинарных файлов
Тем таких много вы можете сказать, но мне нужна помощь именно в ситуации, если вас не затруднит есть четыре листа List&lt;double&gt;...

Чтение и запись бинарных файлов
Привет. Искал решение возможности записи и чтения бинарных файлов. Нагуглил две темы: ...

10
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 02:02
Структуры с такими полями (string) не годятся для записи бинарным методом (write) в файл.
Запись и чтение структуры с файла
Сначала читаете из файла, а потом записываете в файл? Это как?
1
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 08:47  [ТС]
alsav22, ну если файл еще не создан, то и не читается ничего.
Окей, проблему, кажется понял, я так понимаю, мне придется в два потока записывать данные в файл, string в текстовом виде и остальное в бинарном? Или есть какое то другое решение задачки?
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2223 / 1425 / 420
Регистрация: 16.05.2013
Сообщений: 3,642
Записей в блоге: 6
08.09.2014, 08:56
Цитата Сообщение от trev Посмотреть сообщение
Окей, проблему, кажется понял, я так понимаю, мне придется в два потока записывать данные в файл, string в текстовом виде и остальное в бинарном? Или есть какое то другое решение задачки?

Все значительно проще. В классе string есть метод c_str который возвращает си строку. Вот и пишите ее в файл. Только не забудте поместить в файл информацию о длине этой строки.
1
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 14:43  [ТС]
Ilot, Мы не ищем легких путей
а вообще, инфу принял, буду разбираться
всем спс <3

Добавлено через 5 часов 8 минут
Выручайте
С записью в файл, вроде, все ок..
а вот с чтением из файла проблемы =\
P.S. Переделал под ООП.

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
//Person.h
#include <string>
#include <iostream>
#include <fstream>
#include <cstring>
#pragma warning(disable : 4996)
 
const char *file = "d://person11.bin";
 
class Person {
    std::string name;
    int age;
    double height;
public:
    //конструкторы
    explicit Person(const std::string &name_, int age_, double height_)
        : name(name_), age(age_), height(height_) { }
    Person(const Person &ps) 
        : name(ps.name), age(ps.age), height(ps.height) { }
    //методы bin_write и bin_read
    void bin_write() {
        std::ofstream fout(file, 
            std::ios_base::out | std::ios_base::app | std::ios_base::binary);
        if (!fout.is_open()) {
            std::cerr << "ERROR\n";
            exit(EXIT_FAILURE);
        }
        else {
            char *cstr = new char[name.length() + 1];
            std::strcpy(cstr, name.c_str());
            fout.write((char *)&cstr, sizeof(cstr));
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            delete[] cstr;
            fout.close();
        }
    }
    void bin_read() {
        std::ifstream fin;
        fin.open(file, std::ios_base::in | std::ios_base::binary);
        if (fin.is_open()) {
            std::cout << "Данные в файле \"person2.max\":\n";
            unsigned int kol = 0;
            char *cstr = new char[name.length() + 1];
            while (!fin.eof()) {
                fin.read((char *)&cstr, sizeof(cstr) * CHAR_BIT);
                std::cout << kol + 1 << ") " << cstr;
                fin.read((char *)&age, sizeof(age));
                std::cout << ", возраст " << age;
                fin.read((char *)&height, sizeof(height));
                std::cout << ", рост " << height << '\n';
                kol++;
            }
            fin.close();
        }
    }
    //деструктор
    ~Person() { }
};
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 17:11
Цитата Сообщение от trev Посмотреть сообщение
ну если файл еще не создан, то и не читается ничего.
Ну, да. Это я туплю.
0
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 17:19  [ТС]
нашел на форуме такой вот пост по теме..
Цитата Сообщение от I.M. Посмотреть сообщение
...или извращаться с бинарным файлом и строкой дальше)
при записи данных в файл - перед каждой строкой надо вначале записывать ее длину, а затем только само содержимое строки. также надо использовать не sizeof(std::string), а вызывать метод size() у этой строки.
при чтении из файла - вначале считываете длину будущей строки, создаете временный массив char* соответствующей длины, в него считываете данные из файла и только потом переносите этот массив в нужную std::string...
То есть с записью в файл я, кажется, разобрался :
C++
1
2
3
4
5
6
7
char *cstr = new char[name.length() + 1];
            std::strcpy(cstr, name.c_str());
            fout.write((char *)&cstr, name.size());
            delete[] cstr;
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            fout.close();
а вот с чтением вообще туплю дико уже несколько часов к ряду.. Судя по цитате, нужно считать длинну будущей строки.. а вот как это сделать хз.. =\
пока есть вот такой код по чтению из файла, но он не работает
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
std::cout << "Данные в файле \"" << file << "\":\n";
            unsigned int kol = 0;
            while (!fin.eof()) {
                char *cstr = new char[name.length() + 1];
                fin.read((char *)&cstr, name.size());
                std::cout << kol + 1 << ") " << cstr;
                fin.read((char *)&age, sizeof(age));
                std::cout << ", возраст " << age;
                fin.read((char *)&height, sizeof(height));
                std::cout << ", рост " << height << '\n';
                kol++;
            }
            fin.close();
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 17:27
Вот это неправильно:
C++
1
fout.write((char *)&cstr, sizeof(cstr));
sizeof() выдаст размер указателя, а не размер массива.
Вижу, что нашли правильный вариант.

Добавлено через 3 минуты
Цитата Сообщение от trev Посмотреть сообщение
То есть с записью в файл я, кажется, разобрался :
Не вижу записи в файл длины строки.

Добавлено через 4 минуты
Вот это неправильно:
C++
1
2
char *cstr = new char[name.length() + 1];
fin.read((char *)&cstr, name.size()); // !!! просто cstr
Сначала нужно прочитать из файла длину строки (сначала, естественно, записать её туда). Потом создать массив нужного размера, потом прочитать туда саму строку. И не нужно брать адрес у указателя - &cstr, просто cstr (это и так адрес).
1
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 17:32  [ТС]
alsav22,
теперь правильно записываю файл?
C++
1
2
3
4
5
6
7
8
9
10
char *cstr = new char[name.length() + 1];
            std::strcpy(cstr, name.c_str());
            unsigned int *len = new unsigned int(name.length() + 1);
            fout.write((char *)len, sizeof(len));
            fout.write((char *)cstr, name.size());
            delete[] cstr;
            delete[] len;
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            fout.close();
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 18:28
Лучший ответ Сообщение было отмечено trev как решение

Решение

Цитата Сообщение от trev Посмотреть сообщение
теперь правильно записываю файл?
Я бы так сделал:
C++
1
2
3
4
5
6
    int length = name.size();
    fout.write((char *)&length, sizeof(length)); // записываем размер строки
    fout.write((char *)name.c_str(), name.size()); // записываем строку
    fout.write((char *)&age, sizeof(age));
    fout.write((char *)&height, sizeof(height));
    fout.close();
Добавлено через 26 минут
Тогда чтение строки, как-то так будет (в итерации):
C++
1
2
3
4
5
6
7
        int length;
        fin.read((char *)&length, sizeof(length)); // читаем размер строки
        char* cstr = new char[length + 1]; // массив под строку
        fin.read((char *)cstr, length); // читаем строку
        cstr[length] = '\0'; // делаем из массива Си строку
        name = cstr; // заносим массив в string 
        delete [] cstr;
Добавлено через 11 минут
И ещё... Чтобы избежать пустого чтения (когда EOF уже считан, а итерация ещё не закончена), проверку на EOF нужно сделать после считывания размера строки.
1
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 20:14  [ТС]
Цитата Сообщение от alsav22 Посмотреть сообщение
int length = name.size();
здесь точно все правильно? не
C++
1
length = name.length()
Добавлено через 7 минут
сори, туплю.. это одно и тоже..)

Добавлено через 1 час 6 минут
Выкладываю готовый вариант, может кому пригодится
Благодарю за помощь!
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
68
69
70
71
//определение класса
//person.h
#include <string>
#include <iostream>
#include <fstream>
 
#ifndef PERSON_H_
#define PERSON_H_
 
 
const char *file = "d://person.bin";
 
class Person {
    std::string name;
    int age;
    int height;
public:
    //конструкторы
    Person() 
        : name("nobody"), age(0), height(0) { }
    Person(const std::string &name_, int age_ = 0, int height_ = 0)
        : name(name_), age(age_), height(height_) { }
    Person(const Person &ps)
        : name(ps.name), age(ps.age), height(ps.height) { }
    //методы bin_write и bin_read
    void bin_write() const {
        std::ofstream fout(file,
            std::ios_base::out | std::ios_base::app | std::ios_base::binary);
        if (!fout.is_open()) {
            std::cerr << "ERROR\n";
            exit(EXIT_FAILURE);
        }
        else {
            unsigned int len = name.size();
            fout.write((char *)&len, sizeof(len));          //записываем длину строки
            fout.write((char *)name.c_str(), name.size());  //записываем строку
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            fout.close();
        }
    }
    void bin_read() {
        std::ifstream fin;
        fin.open(file, std::ios_base::in | std::ios_base::binary);
        if (fin.is_open()) {
            std::cout << "Данные в файле \"" << file << "\":\n";
            unsigned int kol = 1;
            do {
                int len;
                fin.read((char *)&len, sizeof(len));
                if (fin.eof())
                    break;
                char *cstr = new char[len + 1];
                fin.read((char *)cstr, len);
                cstr[len] = '\0';
                name = cstr;
                delete[] cstr;
                fin.read((char *)&age, sizeof(age));
                fin.read((char *)&height, sizeof(height));
                std::cout << kol << ") " << name
                    << ", возраст: " << age
                    << ", рост: " << height << '\n';
                kol++;
            } while (fin.good());
            fin.close();
        }
    }
    //деструктор
    ~Person() { }
};
#endif // !PERSON_H_
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//main.cpp
#include "stdafx.h"
#include "Person.h"
#include "ctime"
 
int main() {
    setlocale(0, "");
    std::srand(time(NULL));
    Person *man = new Person[4];
    man[0] = Person("Maks", 15 + rand() % 20, 120 + rand() % 100);
    man[1] = Person("Stas", 15 + rand() % 20, 120 + rand() % 100);
    man[2] = Person("Rost", 15 + rand() % 20, 120 + rand() % 100);
    man[3] = Person("Volod'ka", 20 + rand() % 30, 120 + rand() % 100);
    for (int i = 0; i < 4; i++) {
        man[i].bin_write();
        if (i == 3)
            man[i].bin_read();
    }
    system("pause");
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.09.2014, 20:14
Помогаю со студенческими работами здесь

Запись и чтение бинарных файлов
Здравствуйте. Возник вопрос: задание считать текстовый файл и записать его в бинарник по одной строке, как это происходит: пишим длину...

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

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

Чтение бинарных файлов
Не понимаю в чем ошибка. Задача: записать и вывести массивы ФИО и видов спорта, записанных в бинарные файлы. Выводит на консоль не...

Чтение бинарных файлов
посчитать количество байт между первым 0A и FF?


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru