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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.92
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
#1

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

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

Задача - удалить записанный экземпляр класса из дв. файла.
(В моём решении, удаленный экземпляр просто затирается последним)
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*& (с ссылкой)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.10.2012, 07:18     Удалить записанный экземпляр класса из двоичного файла
Посмотрите здесь:

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

Классы и объекты в С++, компонента класса и экземпляр класса - C++
Вариант 8. ИЗДЕЛИЕ наименование– char* шифр– char* тип упаковки– char* количество– int 1. Определить пользовательский ...

Создать экземпляр класса по ссылке экземпляра класса - C++
Есть класс для обработки клиентов // Абстрактный class ClientProcessing { }; Я создаю от него наследника class...

Считать из файла массив записанный в столбик - C++
Здравствуйте. Помогите пожалуйста, я очень старалась в гугле поискать, но все программы выдаваемые, показались мне очень запутанными....

TLS экземпляр класса - C++
Так и не нашёл окончательного ответа на просторах интернета. Можно ли каким-либо образом создать TLS экземпляр объекта (будь то просто...

Указатель на экземпляр шаблонного класса - C++
Есть шаблон класса template &lt;typename TBase&gt; class TArray { ... };, есть некие объекты TArray &lt;A&gt; a; TArray &lt;A&gt; b; TArray &lt;A&gt; c;,...

Ссылка на экземпляр класса в DLL - C++
Написал маленький каркасик для собственново фреймворка, и проблема возникла когда хотель экспортировать его в DLL. Фреймворк предпологает...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
29.10.2012, 18:30     Удалить записанный экземпляр класса из двоичного файла #16
Покажите, как Вы вызываете fseek.
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 18:50     Удалить записанный экземпляр класса из двоичного файла #17
Объекты в файле как записаны? Непрерывная последовательность? Без разделителей?

Добавлено через 2 минуты
Цитата Сообщение от nexen Посмотреть сообщение
Считываю запись с текущего места (то есть должна быть 2ка,
Если строго по примеру, то будет не 2-ка, а пробел.
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 18:52  [ТС]     Удалить записанный экземпляр класса из двоичного файла #18
Toshkarik, в первом сообщении темы. Строки 17-20.

alsav22, ну это я для наглядности. Пробелов нет. Записываемые классы представляют из себя строго фиксированную последовательность байт. vector/string или подобные нет. Только char*. Только с одинаковым new[STRING_SIZE].
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 18:59     Удалить записанный экземпляр класса из двоичного файла #19
Зачем цикл, если нужно переписать один объект?
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 19:20  [ТС]     Удалить записанный экземпляр класса из двоичного файла #20
alsav22, планирую добавить удаление не только по id, так что оставил так.
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 23:04     Удалить записанный экземпляр класса из двоичного файла #21
В предыдущих постах ты пишешь: это помогает, то помогает... То есть, решение проблемы у тебя есть? Просто хочешь знать, почему возникает ошибка? Или нет решения?


Цитата Сообщение от nexen Посмотреть сообщение
Записываю 4. (EOF не ставится, ибо не конец файла)
*В файле сейчас : 4 4 2 3 4*
Уменьшаю count на 1.
Считываю запись с текущего места (то есть должна быть 2ка, но тут происходит не пойми что и считывается как будто пара байт из 4ки и пара байт из 2ки и выходит 00 00 02 00 (если уже к примеру говорить).
Эту причину нешёл. После записи сделай fflush(FILE *f) . Запись в буфер идёт и нужно, чтобы изменения (перед чтением) попали в файл.
И насчёт конца файла. Проверь, правильно ли читаешь последний объект в файле. Как у тебя чтение сделано не видно, но если читать с начала объекта, и читать количество байтов, равное размеру объекта, то признак конца файла не установится. Установится, если чтение сделано именно до конца файла, или начато не с той (большей) позиции.
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
30.10.2012, 06:50  [ТС]     Удалить записанный экземпляр класса из двоичного файла #22
alsav22, Т_Т.. А ведь я же проверял fflush.. Видать я его перед считыванием ставил и почему-то так не срабатывало. Поставил после PrintFile и теперь всё в порядке.
Можете пояснить, почему это помогло? Ведь, если запись идет в буфер, то нам все равно не важно это, так как fread так же читает из буфера, а не из файла, разве нет?
kertio
26 / 26 / 1
Регистрация: 20.09.2011
Сообщений: 68
30.10.2012, 07:56     Удалить записанный экземпляр класса из двоичного файла #23
Цитата Сообщение от nexen Посмотреть сообщение
alsav22, Т_Т.. А ведь я же проверял fflush.. Видать я его перед считыванием ставил и почему-то так не срабатывало. Поставил после PrintFile и теперь всё в порядке.
Можете пояснить, почему это помогло? Ведь, если запись идет в буфер, то нам все равно не важно это, так как fread так же читает из буфера, а не из файла, разве нет?
Ты немного не про тот буфер думаешь. буфер записи на винчестер. система кэширует данные в буфере для ускорения операций чтения записи данных. после того как ты записал данные в файл(точнее даже в дескриптор) они пишутся в буфер записи на винчестер. через какое-то время они запишутся физически на диск, не ранее. можно самому эту синхронизацию вызвать через fflush, а можно просто подождать, например через паузу. а буфер чтения это уже другое. поэтому ты и не можешь читать напрямую из буфера, в который ты записал данные. примерно так. это касательно Linux\Unix. хотя и в виндовс скорее всего тоже самое.
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2012, 16:49     Удалить записанный экземпляр класса из двоичного файла #24
Цитата Сообщение от nexen Посмотреть сообщение
Можете пояснить, почему это помогло?
Нет, сам не понимаю. Думаю, тут дело в том, что файл открыт одновременно для записи и чтения. Как в таком случае буфер организован, без понятия. Самое интересное в том, что тут не просто чтение неправильно происходит, но и запись в файл, в результате, получится неправильная. Чтение сдвигает курсор для записи? Ещё помогает, если после записи просто указать (через fseek()) откуда читать.
nexen
187 / 180 / 3
Регистрация: 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 не нашел..
kertio
26 / 26 / 1
Регистрация: 20.09.2011
Сообщений: 68
30.10.2012, 17:19     Удалить записанный экземпляр класса из двоичного файла #26
kertio, если честно, ничего не понял : ) Постараюсь разобраться чуть позже.
Есть ли у тебя ссылка, где можно почитать о таком? Я раньше никогда fflush не использовал и все работа корректно. Подобных ошибок, как у меня, у кого-то ещё в google не нашел..[/QUOTE]

На самом деле ничего сложно тут нет.
ну вроде бы тут описано.
http://itc.ua/forum/showthread.php?t=40057
Будут вопросы, постараюсь объяснить как смогу.
alsav22
5416 / 4812 / 442
Регистрация: 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;
}
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
30.10.2012, 18:28  [ТС]     Удалить записанный экземпляр класса из двоичного файла #28
alsav22, у меня подобная конструкция не приводит к порче записи.. Лишь к порче чтения :<
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
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.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.10.2012, 19:54     Удалить записанный экземпляр класса из двоичного файла
Еще ссылки по теме:

Функция, возвращающая экземпляр класса - C++
Доброго времени суток. Допустим есть у нас функция, результатом которой является некий объект: MyClass* func() { ... ...

Указатель на текущий экземпляр класса this - C++
Всем здрасьте. Например у меня есть класс: class A { // ... void B(); void C(); // ... }

указатель на экземпляр шаблонного класса - C++
имеется такой класс template &lt;class Coord&gt; class Elem { private: const Coord x, y; Elem *Prev; bool check; public: ...

В начало двоичного файла целого типа дописать нечетные элементы этого файла. - C++
Вот прога для записи четных файлов...в конец Мне нужно в начало....нечетные...помогите разобраться как сделать!!!:drink: #include...

Передача указателей на функции в экземпляр класса - C++
Есть класс главного окна,класс содержит такой метод public: void pFuncTake( void (*p1)(char *path), void (*p2)(), void (*p3)(),void...


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

Или воспользуйтесь поиском по форуму:
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2012, 19:54     Удалить записанный экземпляр класса из двоичного файла #30
Цитата Сообщение от nexen Посмотреть сообщение
alsav22, у меня подобная конструкция не приводит к порче записи.. Лишь к порче чтения :<
На моём коде проверял? Среда какая?

Добавлено через 16 минут
Я в Студии проверял и в Code Blocks. Разница только в том, что во втором варианте, в Code Blocks, не мусор, а пустота выводится, и в файле получается: 678пробелы678"
Yandex
Объявления
30.10.2012, 19:54     Удалить записанный экземпляр класса из двоичного файла
Ответ Создать тему
Опции темы

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