Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вставка записей в бинарный файл 
:(
    Опции темы
shaukote
Дата 24.4.2013, 00:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 13.2.2013

Репутация: нет
Всего: нет



Всем доброго времени суток.

Встала у меня задача заполнить бинарный файл структурами по возрастанию (некоторого поля).
Соответственно понадобилось как-то вставлять записи в файл.
Я написал довольно очевидный, вроде бы код:
Код

#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <io.h>

using std::cout;
using std::endl;

// структура, которыми будет заполняться файл
struct fileEntry {
    char str[8];
    long number;
};

const size_t size = sizeof(fileEntry);

bool insert(fileEntry, long, FILE*); // вставка записи
bool shift(long, long, FILE*); // сдвиг имеющихся записей для освобождения места
void output(FILE*); // вывод файла

int main()
{
    FILE *file;
    fopen_s(&file, "..\\test", "w+b");

    fileEntry empty;
    strcpy_s(empty.str, sizeof(empty.str), "empty");
    for (int i = 0; i < 5; ++i) {
        empty.number = i;
        fwrite(&empty, size, 1, file);
    }
    output(file);

    fileEntry entry;
    entry.number = 42;
    strcpy_s(entry.str, sizeof(entry.str), "test");

    insert(entry, 2, file);

    output(file);

    fclose(file);
    system("PAUSE");

    return 0;
}

bool insert(fileEntry entry, long pos, FILE* file)
{
    shift(pos, _filelength(fileno(file)) / size - 1, file);
    output(file);

    fseek(file, pos * size, SEEK_SET);
    size_t code = fwrite(&entry, size, 1, file);
    fflush(file);

    return (1 == code);
}

bool shift(long first, long last, FILE* file)
{
    size_t correct = 0;
    fileEntry buffer;

    for (long i = last; i >= first; --i) {
        fseek(file, i * size, SEEK_SET);
        correct += fread(&buffer, size, 1, file);
        correct -= fwrite(&buffer, size, 1, file);
    }
    fflush(file);

    return (0 == correct);
}

void output(FILE* file)
{
    rewind(file);
    fileEntry entry;

    while (fread(&entry, size, 1, file))
        cout << entry.number << " : " << entry.str << endl;
    cout << endl;
}

 
Однако пресловутая функция shift() не работает, увы. То есть она не то, чтобы не сдвигает записи в файле, она вообще его не меняет.  
Буду рад, если кто-нибудь ткнёт меня носом в проблему, поскольку я её найти не могу.  smile

UPD
Слегка модифицировал функцию shift(), добавил, так сказать, отладочный вывод, чтобы понять, что вообще происходит:
Код

bool shift(long first, long last, FILE* file)
{
    size_t correct = 0;
    fileEntry buffer;

    for (long i = last; i >= first; --i) {
        fseek(file, i * size, SEEK_SET);
        cout << "\t" << ftell(file) / size;

        correct += fread(&buffer, size, 1, file);
        cout << "->" << ftell(file) /size;

        correct -= fwrite(&buffer, size, 1, file);
        cout << "->" << ftell(file) / size;
        cout << endl;
    }
    fflush(file);

    return (0 == correct);
}
 
Получил, что указатель в файле движется так:
4->5->5
3->4->5
2->3->4

То, есть он вроде передвигается как надо (но на последнем - пятом - элементе почему-то не сдвигается в третий раз), но никакие изменения в файл не вносятся.  smile 

Это сообщение отредактировал(а) shaukote - 24.4.2013, 00:30
PM MAIL   Вверх
feodorv
Дата 24.4.2013, 11:22 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Потоки плохо переваривают непосредственный переход от чтения к записи:
Цитата(shaukote @  24.4.2013,  01:18 Найти цитируемый пост)
    for (long i = last; i >= first; --i) {
        fseek(file, i * size, SEEK_SET);
        cout << "\t" << ftell(file) / size;
        correct += fread(&buffer, size, 1, file);
        fseek(file, (i+1) * size, SEEK_SET);
        cout << "->" << ftell(file) /size;
        correct -= fwrite(&buffer, size, 1, file);
        cout << "->" << ftell(file) / size;
        cout << endl;
    }

Цитата

For files open for appending (those which include a "+" sign), on which both input and output operations are allowed, the stream should be flushed (fflush) or repositioned (fseek, fsetpos, rewind) between either a writing operation followed by a reading operation or a reading operation which did not reach the end-of-file followed by a writing operation.



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
shaukote
Дата 24.4.2013, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 13.2.2013

Репутация: нет
Всего: нет



feodorv, спасибо, помогло.
Скажите, а есть какое-то объяснение у такого, кхм, "явления"?..
PM MAIL   Вверх
feodorv
Дата 25.4.2013, 08:53 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Насколько я помню, какие-то проблемы с буферизацией (буфер на чтение и на запись один и тот же).

Это сообщение отредактировал(а) feodorv - 25.4.2013, 20:00


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
shaukote
Дата 25.4.2013, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 13.2.2013

Репутация: нет
Всего: нет



feodorv, ясно, спасибо.  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0685 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.