С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
1

Удалить записанный экземпляр класса из двоичного файла

24.10.2012, 07:18. Показов 2614. Ответов 34
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Задача - удалить записанный экземпляр класса из дв. файла.
(В моём решении, удаленный экземпляр просто затирается последним)
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
for (UINT i=0; i<patientsCount; ++i)
    {
        //fseek(patientsDatabase, (sizeof(patientsCount)+i*Size()), SEEK_SET); // X-ACTION
        ReadFile(patientsDatabase); //считываю экземпляр класса из дв. файла. Это метод\
Всё происходит в this
        if (_id == idRequired) // Требуемый Id для удаления
        {
            //DeleteCard(databases);
            if (patientsRequiredCount == 0)
                printf(Rus("-\nУдаленные записи\n"));
            printf(Rus("\nЗапись #%u\n"), i+1);
            //Print(); 
            PrintIdFile(patientsIdDatabase); // записываю this в дв. файл
            if (i < (patientsCount-1))
            {
                fseek(patientsDatabase, (sizeof(patientsCount)+(patientsCount-1)*Size()), SEEK_SET); // перехожу к последней записи дв. файла (Size() - размер структуры. Считает корректно)
                ReadFile(patientsDatabase); // считываю this
                fseek(patientsDatabase, (sizeof(patientsCount)+i*Size()), SEEK_SET); // перехожу к удаляемой записи
                PrintFile(patientsDatabase); // перезаписываю её
            }
            ++patientsRequiredCount;
            --patientsCount; // уменьшаю счетчик кол-ва записей
        }
    }
Проблема в том, что она не работает, если оставить всё так, как есть. Если разкомментировать строчку с fseek X-MOMENT, то всё начнет работать. Причем сам fseek никуда не двигает каретку в дв. файле. До X-MOMENT каретка стоит на 104 байте, после момента так же на 104 байте, но при этом следующий за ней ReadFile считывает все корректно.
Отчего такая феерическая ошибка? Может ли быть так, что, когда я сделал fseek на последнюю запись и считал её (ушел в EOF), то как-то нарушил всю суть работы? Хотя PrintFile после возврата каретки на текущую запись всё же отработал D:

Добавлено через 6 минут
Вместо X-ACTION можно вставить и такое. Тоже поможет :
C++
1
2
3
UINT id;
        fread(&id, sizeof(id), 1, patientsDatabase);
        fseek(patientsDatabase, -long(sizeof(id)), SEEK_CUR);
Ещё помогает передача параметра в ReadFile в виде FILE*& (с ссылкой)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.10.2012, 07:18
Ответы с готовыми решениями:

Можно ли считывать поля класса из двоичного файла одним fread
Можно ли считывать поля класса из двоичного файла одним fread? fread(this, sizeof(*this), 1,...

Создать экземпляр одного класса в Main, и передать его в экземпляр другого класса
Добрый день. Подскажите пожалуйста. есть несколько классов-файлов в одном пакете. class one...

Удалить экземпляр класса в массиве
в клсассе Group нужен метод удаления студента из группы по номеру зачетной книжки, как правильно...

Сборщик мусора (как удалить экземпляр класса)
В классе Main при клике на спрайт создаётся экземпляр класса Window: var window:Window; ......

34
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 23:04 21
Author24 — интернет-сервис помощи студентам
В предыдущих постах ты пишешь: это помогает, то помогает... То есть, решение проблемы у тебя есть? Просто хочешь знать, почему возникает ошибка? Или нет решения?


Цитата Сообщение от nexen Посмотреть сообщение
Записываю 4. (EOF не ставится, ибо не конец файла)
*В файле сейчас : 4 4 2 3 4*
Уменьшаю count на 1.
Считываю запись с текущего места (то есть должна быть 2ка, но тут происходит не пойми что и считывается как будто пара байт из 4ки и пара байт из 2ки и выходит 00 00 02 00 (если уже к примеру говорить).
Эту причину нешёл. После записи сделай fflush(FILE *f) . Запись в буфер идёт и нужно, чтобы изменения (перед чтением) попали в файл.
И насчёт конца файла. Проверь, правильно ли читаешь последний объект в файле. Как у тебя чтение сделано не видно, но если читать с начала объекта, и читать количество байтов, равное размеру объекта, то признак конца файла не установится. Установится, если чтение сделано именно до конца файла, или начато не с той (большей) позиции.
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
30.10.2012, 06:50  [ТС] 22
alsav22, Т_Т.. А ведь я же проверял fflush.. Видать я его перед считыванием ставил и почему-то так не срабатывало. Поставил после PrintFile и теперь всё в порядке.
Можете пояснить, почему это помогло? Ведь, если запись идет в буфер, то нам все равно не важно это, так как fread так же читает из буфера, а не из файла, разве нет?
0
26 / 26 / 3
Регистрация: 20.09.2011
Сообщений: 68
30.10.2012, 07:56 23
Цитата Сообщение от nexen Посмотреть сообщение
alsav22, Т_Т.. А ведь я же проверял fflush.. Видать я его перед считыванием ставил и почему-то так не срабатывало. Поставил после PrintFile и теперь всё в порядке.
Можете пояснить, почему это помогло? Ведь, если запись идет в буфер, то нам все равно не важно это, так как fread так же читает из буфера, а не из файла, разве нет?
Ты немного не про тот буфер думаешь. буфер записи на винчестер. система кэширует данные в буфере для ускорения операций чтения записи данных. после того как ты записал данные в файл(точнее даже в дескриптор) они пишутся в буфер записи на винчестер. через какое-то время они запишутся физически на диск, не ранее. можно самому эту синхронизацию вызвать через fflush, а можно просто подождать, например через паузу. а буфер чтения это уже другое. поэтому ты и не можешь читать напрямую из буфера, в который ты записал данные. примерно так. это касательно Linux\Unix. хотя и в виндовс скорее всего тоже самое.
1
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2012, 16:49 24
Цитата Сообщение от nexen Посмотреть сообщение
Можете пояснить, почему это помогло?
Нет, сам не понимаю. Думаю, тут дело в том, что файл открыт одновременно для записи и чтения. Как в таком случае буфер организован, без понятия. Самое интересное в том, что тут не просто чтение неправильно происходит, но и запись в файл, в результате, получится неправильная. Чтение сдвигает курсор для записи? Ещё помогает, если после записи просто указать (через fseek()) откуда читать.
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
30.10.2012, 17:05  [ТС] 25
alsav22, я делал так, как будто fread и fwrite имеют общую позицию в файле, то есть, если мы прочитали первую запись fread, то, испоьзовав после неё fwrite, писать начнет со второй записи. Так оно и происходило, разве что fread колбасило. fwrite отрабатывало корректно. Проверял ручками дв. файл, байты нормальные.
Поставил везде fflush и всё заработало так, как нужно. Ну как везде.. Если есть чтение - не ставлю. Если есть запись - ставлю ТОЛЬКО после последнего блока. Если есть пара блоков чтения и записи, и они между собой перекликаются, ставлю перед каждым чтением. Пример :

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
//1
fread();
fread();
fread();
//END
 
//2
fwrite();
fwrite();
fwrite();
fflush();//
//END
 
//3
fwrite();
fwrite();
fflush();//
fread();
fwrite();
fflush();//
fread();
fwrite();
fflush();//
//END
Параметры функций опущены.


kertio, если честно, ничего не понял : ) Постараюсь разобраться чуть позже.
Есть ли у тебя ссылка, где можно почитать о таком? Я раньше никогда fflush не использовал и все работа корректно. Подобных ошибок, как у меня, у кого-то ещё в google не нашел..
0
26 / 26 / 3
Регистрация: 20.09.2011
Сообщений: 68
30.10.2012, 17:19 26
kertio, если честно, ничего не понял : ) Постараюсь разобраться чуть позже.
Есть ли у тебя ссылка, где можно почитать о таком? Я раньше никогда fflush не использовал и все работа корректно. Подобных ошибок, как у меня, у кого-то ещё в google не нашел..[/QUOTE]

На самом деле ничего сложно тут нет.
ну вроде бы тут описано.
http://itc.ua/forum/showthread.php?t=40057
Будут вопросы, постараюсь объяснить как смогу.
1
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2012, 18:08 27
Цитата Сообщение от alsav22 Посмотреть сообщение
Самое интересное в том, что тут не просто чтение неправильно происходит, но и запись в файл, в результате, получится неправильная.
Я вот об этом (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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// 1 вариант (после записи нет чтения)
 
#include <fstream>
#include<iostream>
#include <cstdlib>
using namespace std;
 
int main()
{
    FILE *f = fopen("f.txt", "r+b"); // в файле: 012345678
     
    unsigned char x = 'x', y = 'y', z = 'z';
    
                fseek(f, 6, SEEK_SET); // читаем, начиная с 6
    fread(&x, 1, 1, f);
    fread(&y, 1, 1, f);
    fread(&z, 1, 1, f);
    
    fseek(f, 0, SEEK_SET); // записываем, начиная с 0
    fwrite(&x, 1, 1, f);
    fwrite(&y, 1, 1, f);
    fwrite(&z, 1, 1, f);
    
    // в результате в файле:  678345678
    system("pause");
    return 0;
}
 
// 2 вариант (после записи нет fflush(f)  и сразу чтение; запись в файл неправильная)
 
#include <fstream>
#include<iostream>
#include <cstdlib>
using namespace std;
 
int main()
{
    FILE *f = fopen("f.txt", "r+b"); // в файле: 012345678
     
    unsigned char x = 'x', y = 'y', z = 'z';
    
                fseek(f, 6, SEEK_SET); // читаем, начиная с 6 
    fread(&x, 1, 1, f);
    fread(&y, 1, 1, f);
    fread(&z, 1, 1, f);
    
    fseek(f, 0, SEEK_SET); // записываем, начиная с 0
    fwrite(&x, 1, 1, f);
    fwrite(&y, 1, 1, f);
    fwrite(&z, 1, 1, f);
    
    x = 'x', y = 'y', z = 'z';
    
    fread(&x, 1, 1, f);   // продолжаем читать (откуда непоятно. С буфера записи?)
    cout << x << endl; // выводит мусор (код 205)
    fread(&y, 1, 1, f);
    cout << y << endl; // выводит мусор
    fread(&z, 1, 1, f);
    cout << z << endl;  // выводит мусор
    
    // в результате в файле:  678ННН678 // неправильная запись
    system("pause");
    return 0;
}
 
// 3 вариант (с fflush(f) после записи).
 
#include <fstream>
#include<iostream>
#include <cstdlib>
using namespace std;
 
int main()
{
    FILE *f = fopen("f.txt", "r+b"); // в файле: 012345678
     
    unsigned char x = 'x', y = 'y', z = 'z';
    
                fseek(f, 6, SEEK_SET); // читаем, начиная с 6 
    fread(&x, 1, 1, f);
    fread(&y, 1, 1, f);
    fread(&z, 1, 1, f);
    
    fseek(f, 0, SEEK_SET); // записываем, начиная с 0
    fwrite(&x, 1, 1, f);
    fwrite(&y, 1, 1, f);
    fwrite(&z, 1, 1, f);
    
    fflush(f);
 
    x = 'x', y = 'y', z = 'z';
    
    fread(&x, 1, 1, f); // продолжаем читать c 3
    cout << x << endl;          // выводит 3
    fread(&y, 1, 1, f);
    cout << y << endl;          // выводит 4
    fread(&z, 1, 1, f);
    cout << z << endl;          // выводит 5
    
     // в результате в файле:  678345678 
     system("pause");
     return 0;
}
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
30.10.2012, 18:28  [ТС] 28
alsav22, у меня подобная конструкция не приводит к порче записи.. Лишь к порче чтения :<
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
30.10.2012, 18:44 29
kertio, причем здесь ОС и кеширование HDD? Программа знать не знает, как происходят операции записи/чтения, она всего лишь делает запросы. ОС сама решает записывать данные сразу на диск сейчас или потом, для программы эти данные уже записаны.

nexen, про fflush:
In files open for update (i.e., open for both reading and writting), the stream shall be flushed after an output operation before performing an input operation.
1
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2012, 19:54 30
Цитата Сообщение от nexen Посмотреть сообщение
alsav22, у меня подобная конструкция не приводит к порче записи.. Лишь к порче чтения :<
На моём коде проверял? Среда какая?

Добавлено через 16 минут
Я в Студии проверял и в Code Blocks. Разница только в том, что во втором варианте, в Code Blocks, не мусор, а пустота выводится, и в файле получается: 678пробелы678"
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
30.10.2012, 19:55  [ТС] 31
alsav22, ага.
VS 2008.
0
26 / 26 / 3
Регистрация: 20.09.2011
Сообщений: 68
30.10.2012, 20:32 32
Цитата Сообщение от Toshkarik Посмотреть сообщение
kertio, причем здесь ОС и кеширование HDD? Программа знать не знает, как происходят операции записи/чтения, она всего лишь делает запросы. ОС сама решает записывать данные сразу на диск сейчас или потом, для программы эти данные уже записаны.

nexen, про fflush:
чуть чуть конечно не в тему, но все же,как тогда объяснить что на кешируемых фс если вырубить питание, то данные которые не были сброшены sync-ом, читай fflush-ем, теряются? тем более приводишь информацию по функции, и даже не потрудился перевести. после операции out поток должен быть сброшел, перед чтением. или я затупил где-то?
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
30.10.2012, 21:22 33
kertio, буфер потока и кеширование фс/диска разные вещи.
При вызове fflush, или при закрытии файла, данные должны записаться в файл на диске. ОС на свое усмотрение, или записывает сразу данные на диск, или оставляет их в кеше для последующей записи, если диск занят в данный момент другой операцией, все зависит как от самой ОС так и от драйвера устройства. Для программы эти данные уже записаны на носитель. И, естественно, если в тот момент, пока ОС держит данные в кеше, вырубить питание, то данные потеряются. Но повторюсь - для программы файл уже записан.
Цитата Сообщение от kertio Посмотреть сообщение
тем более приводишь информацию по функции, и даже не потрудился перевести.
Ну как бы тут люди не глупые, я думаю, английский технический язык знают, если занимаются программированием.

Но могу перевести:
В файлах, открытых для обновления ( открытых для записи и чтения одновременно ), поток ( тут наверно лучше было бы написать буфер потока ) должен быть сброшен после вывода ( записи в файл, в данном случае ) перед операцией ввода ( чтения из файла, в данном случае ).

Как я понял, это синхронизирует потоки ввода и вывода.

В C++, например, есть функция std::ios::tie для привязки потоков. Так, например, объект std::cin, по умолчанию, "привязан" к объекту std::cout, что гарантирует сброс буфера объекта std::cout перед попыткой ввода с помощью std::cin.
2
26 / 26 / 3
Регистрация: 20.09.2011
Сообщений: 68
31.10.2012, 07:16 34
так вроде бы об этом и шла речь... поэтому и не читаются данные правильно после операций: запись запись запись запись чтение... после записи нужно сделать, грубо говоря commit изменений, а потом читать. и перед тем как писать я прочитал об этой функции. полный справочник шилдта. там есть описание ф-ии.
PS, все равно спасибо. буду больше учить\читать.
1
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
31.10.2012, 20:25 35
Сейчас посмотрел, как это в линукс работает. Там и без fflush() всё корректно отрабатывает. Только после fflush() изменения (записанные) сразу в файле появляются, а если без, то после первой операции чтения (если в отладке смотреть, а скорее всего, перед первой операцией чтения). Наверное, в линукс синхронизация записи/чтения из файла сделана так же, как для cin/cout (как Toshkarik описывал в 33 посте).
Цитата Сообщение от Toshkarik Посмотреть сообщение
... Так, например, объект std::cin, по умолчанию, "привязан" к объекту std::cout, что гарантирует сброс буфера объекта std::cout перед попыткой ввода с помощью std::cin.
1
31.10.2012, 20:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.10.2012, 20:25
Помогаю со студенческими работами здесь

Создать экземпляр метода класса или доступ к методу из экземпляра класса
Всем доброго времени суток!) Уже месяца как 2 не сишарпил и подзабыл...собственно задача такая:...

Как получить ссылку на текущий экземпляр класса внутри этого класса?
Как? Чтобы отрабатывал деструктор! и в нем можно было поиметь этот this ... Идея в том, что пишу...

Экземпляр класса как входные данные метода другого класса
Можно ли в качестве входных данных метода передать экземпляр метода другого класса? Если да, то как?

Создание указателя типа базового класса на экземпляр производного класса
Добрый день! Иногда видел коды, где создавался указатель типа базового класса на объект класса -...


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

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru