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

Забекапить и восстановить вектор из файла - C++

Восстановить пароль Регистрация
 
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
02.04.2011, 16:33     Забекапить и восстановить вектор из файла #1
Имею вектор чаровы по 8 бит каждый элемент std::vector<char> muz; вцелом весь вектор занимает около 200 мегабайт.
Нужно в приложение добавить возможность сохранять и восстанавливать на ходу на raid ssd, притом за максимальную скорость, желательно за миллисекунды.
Я представляю это так, узнаю в какой области памяти лежит вектор ... или конкретнее где он начинается и сколько занимает и дальше какой-то специальной функцией копирую его как простую бинарную строку в файл.
Помогите пожалуйста реализовать.

Добавлено через 3 минуты
Вот нашел такой пример для записи:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(void)
{
    FILE *fp;
    size_t count;
    char const *str = "привет\n";
 
    fp = fopen("пример.txt", "wb");
    if(fp == NULL) {
        perror("ошибка открытия пример.txt");
        return EXIT_FAILURE;
    }
    count = fwrite(str, 1, strlen(str), fp);
    printf("Записано %lu байт. fclose(fp) %s.\n", (unsigned long)count, fclose(fp) == 0 ? "успешно" : "с ошибкой");
 
    return 0;
}
Где fwrite (*p, size, n, *f);
Функция записывает n элементов длиной size байт из буфера,заданного указателем p,в поток f. Возвращает число записанных элементов.
Мне получается нужно задать указатель на начало вектора, определить его длину и тогда можно прямиком копировать его в файл, правильно?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.04.2011, 16:33     Забекапить и восстановить вектор из файла
Посмотрите здесь:

Вектор из файла! C++
C++ чтение из файла и запись в вектор
Ввод из файла в вектор C++
C++ Вектор в файл и из файла
Считать вектор из файла, записать вектор в файл C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
02.04.2011, 16:42     Забекапить и восстановить вектор из файла #2
Да, начало данных в std::vector получаете с помощью &a[0](если есть например объявление std::vector<char> a; ), зная действительную длину можно копировать напрямую, так как данные гарантированно будут располагаться линейно.
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
02.04.2011, 17:05  [ТС]     Забекапить и восстановить вектор из файла #3
Вот я ещё одну функцию нашел, тот, кто её написал, сказал что работает очень быстро...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void writeCubeToFile(const std::vector<char> &day_us)
{
    const unsigned int blocksize = 262144; // Наиболее эффективно записывать блоками по 256 килобайт
    unsigned long blocks = distance(day_us.begin(), day_us.end()) / blocksize;
 
    std::ofstream outfile("nanocube.txt", std::ios::out | std::ios::binary);
 
    for(unsigned long i = 0; i <= blocks; i++)
    {
        unsigned long position = blocksize * i;
 
        if(blocksize > distance(day_us.begin() + position, day_us.end()))
             outfile.write(&*(day_us.begin() + position), distance(day_us.begin() + position, day_us.end()));
        else outfile.write(&*(day_us.begin() + position), blocksize);
    }
 
    outfile.write("\0", 1);
 
    outfile.close();
}
но у меня она не работает, помогите пожалуйста поправить

Добавлено через 1 минуту
Ma3a немогли бы вы набросать?
В инете вообще нет ниодного примера такой реализации, везде все решают проблему перебором массива итератором...
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
02.04.2011, 17:28     Забекапить и восстановить вектор из файла #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Kadet89, при необходимости быстрого ввода/вывода файлового я предпочитаю использовать istreambuf_iterator/ostreambuf_iterator, так как они позволяют производить операции с файлами напрямую, в обход ненужного в данном случае форматирования и прочих накладных расходов. Пример сейчас приведу.

Добавлено через 4 минуты
выйдет примерно так:

C++
1
2
3
4
5
6
7
void myOutput(const std::vector<char> &day_us)
    {
    std::ofstream outfile("test.txt", std::ios::out | std::ios::binary);
    std::ostreambuf_iterator<char> it(outfile);
    std::copy(day_us.begin(),day_us.end(),it);
    outfile.close();
    }
Насчет того, что быстрее: блоковый вывод или такой подход, скажу, что при использовании ostreambuf_iterator время незначительно отличается( чего не скажешь о ostream_iterator, которые работают значительно медленнее), так что стоит хорошо рассчитать все риски, прежде чем думать над блоковым выводом, так как в таком случае еще придется подбирать оптимальный размер блока для наибольшей скорости, а здесь такого нет.

Добавлено через 9 минут
Kadet89, а ваша версия не работает потому, что в функцию передается std::vector<uint32_t>, хотя должен бы std::vector<char>, так как outfile.write ожидает указателей на char, а у вас вышел бы не char *, а uint32_t *, что компилятору и не нравится.

Не по теме:

А, уже поправили

CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
02.04.2011, 17:32     Забекапить и восстановить вектор из файла #5
Очень удивила версия с поблочной записью. Неужели программист считал что таким образом обгонит стандартную библиотеку?
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
02.04.2011, 17:35  [ТС]     Забекапить и восстановить вектор из файла #6
Насчет разных типов данных
C++
1
2
3
4
5
6
7
void myOutput(const std::vector<int> &day_us)
        {
        std::ofstream outfile("test.txt", std::ios::out | std::ios::binary);
        std::ostreambuf_iterator<int> it(outfile);
        std::copy(day_us.begin(),day_us.end(),it);
        outfile.close();
        }
если использовать int, то уже почему-то не работает
получается данный метод применим только для char? А как тогда быть если мне понадобится сохранять значения с более чем 256 уровнями? ... всмысле более 8 бит
Очень удивила версия с поблочной записью. Неужели программист считал что таким образом обгонит стандартную библиотеку?
ммм, не знаю, почитайте сами:
_http://stackoverflow.com/questions/1693089/fastest-way-to-write-large-stl-vector-to-file-using-stl
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
02.04.2011, 17:42     Забекапить и восстановить вектор из файла #7
deleted. Не всек чуток.
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
02.04.2011, 17:44     Забекапить и восстановить вектор из файла #8
Kadet89, если бы мы использовали ostream_iterator, то это бы прокатило, но ostreambuf_iterator - более низкоуровневый интерфейс и работает или с обычными потоками и char типом, либо с широкими потоками и wchar_t соответственно.
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
02.04.2011, 17:47  [ТС]     Забекапить и восстановить вектор из файла #9
А как тогда быть? ostream_iterator использовать или тут уже блочная запись возможно выиграет?
Или переводить int в char[4]?
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
02.04.2011, 18:07     Забекапить и восстановить вектор из файла #10
Дак с блочной записью все равно придется иметь дело с ofstream.write, которая как я уже говорил , работает с char const *. Как вариант(да и наверное как оптимальный при учете количества выводимых данных) будет лучше всего воспользоваться чем-то вроде
C++
1
2
std::ofstream outfile("test.txt", std::ios::out | std::ios::binary);
outfile.write((const char *)&day_us[0],sizeof(int) * day_us.size());
Добавлено через 16 минут
если использовать ostreambuf_iterator, то можно и так

C++
1
2
3
4
5
6
7
void myOutput(const std::vector<int> &day_us)
    {
    std::ofstream outfile("test.txt", std::ios::out | std::ios::binary);
    std::ostreambuf_iterator<char> it(outfile);
    std::copy((char *)(&day_us[0]),(char *)(&day_us[0] + day_us.size()),it);
    outfile.close();
    }
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
02.04.2011, 18:26  [ТС]     Забекапить и восстановить вектор из файла #11
Ну и последний вопрос, после записи тогда уж вектора int'ов в файл
C++
1
2
3
4
5
6
7
void myOutput(const std::vector<int> &day_us)
        {
        std::ofstream outfile("test.txt", std::ios::out | std::ios::binary);
        std::ostreambuf_iterator<char> it(outfile);
        std::copy((char *)(&day_us[0]),(char *)(&day_us[0] + day_us.size()),it);
        outfile.close();
        }
как этот вектор из файла восстановить?
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
02.04.2011, 18:33     Забекапить и восстановить вектор из файла #12
Можно так

C++
1
2
3
4
5
6
7
void myInput(std::vector<int> &my)
    {
    std::ifstream infile("test.txt",std::ios::in | std::ios::binary);
    std::istreambuf_iterator<char> it(infile);
    std::copy(it,std::istreambuf_iterator<char>(),(char *)&my[0]);
    infile.close();
    }
только данный код рассчитан на то, что память под хранилище вектора выделена и имеет такой же размер, что и количество байтов, считанное из файла, иначе будут проблемы.
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
03.04.2011, 16:45  [ТС]     Забекапить и восстановить вектор из файла #13
Цитата Сообщение от Ma3a Посмотреть сообщение
...только данный код рассчитан на то, что память под хранилище вектора выделена и имеет такой же размер, что и количество байтов, считанное из файла, иначе будут проблемы.
Ну это не проблема
Большое спасибо

Добавлено через 21 час 44 минуты
Вот собрал всё в кучу, но не заработало. Файл даже не создается. Создал вручную, выставил права на запись, но всёравно приложение в него ничего не заносит...

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
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <fstream>
 
void myOutput(const std::vector<int> &day_us)
        {
        std::ofstream outfile("test.txt", std::ios::out | std::ios::binary);
        std::ostreambuf_iterator<char> it(outfile);
        std::copy((char *)(&day_us[0]),(char *)(&day_us[0] + day_us.size()),it);
        outfile.close();
        }
 
void myInput(std::vector<int> &my)
        {
        std::ifstream infile("test.txt",std::ios::in | std::ios::binary);
        std::istreambuf_iterator<char> it(infile);
        std::copy(it,std::istreambuf_iterator<char>(),(char *)&my[0]);
        infile.close();
        }
 
int main()
{
 
    std::vector<int> day_us;
    std::vector<int> vost;
 
    day_us.resize(10);
    vost.resize(5);
    day_us.reserve(250);
    vost.reserve(250);
 
    day_us.push_back(11);
    day_us.push_back(13);
    day_us.push_back(666);
    day_us.push_back(898);
    day_us.push_back(1028);
 
    myOutput(day_us); // Сохраняем массив в файл
    myInput(vost); // Загружаем массив из файла
 
    for (int i = 0; i < day_us.size(); i++)
        std::cout << "Исход: " << day_us[i] << "\n"; // Выводим массив на запись
 
    for (int a = 0; a < vost.size(); a++)
        std::cout << "Восст: " << vost[a] << "\n"; // Выводим восстановленный массив
 
}
Если занять файл другим приложением, то выводится "Отказано в доступе". Т.е. приложение всётаки его открывает...
Пробовал занести в него значения вручную, но вектор из них не восстановился
Консоль:
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 0
Исход: 11
Исход: 13
Исход: 666
Исход: 898
Исход: 1028
Восст: 0
Восст: 0
Восст: 0
Восст: 0
Восст: 0
конец
Полагаю ошибки в строках 40 и 41?
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
03.04.2011, 17:20     Забекапить и восстановить вектор из файла #14
Kadet89, собственно о чем я и говорил в последнем посте
myInput работает верно только в том случае , когда действительный размер хранилища вектора в байтах равен тому, сколько байтов будет считано из файла( или хотя бы не меньше ). Насчет того, что файл не создается - у меня вот создается и всё хорошо, здесь хз. По поводу того, что не восстанавливается вектор, проследим работу вашей программы и всё станет сразу ясно:

1) Сначала day_us и vost содержат 10 и 5 нулевых элементов соответственно( resize'ы ), то есть фактический размер их -- 10 и 5.
2) Вы забиваете в day_us еще 5 элементов, то есть day_us.size() == 15
3) Вы вызываете reserve для обоих векторов - это выделяет память под хранилище обоих векторов на 250 элементов, но действительные размеры векторов остались по-прежнему 15 и 5.
4) С myOutput должно быть всё ясно
5) После myInput в vost нормально копируются 15 элементов( потому что вы зарезервировали место под 250 элементов), которые были в day_us, но их вы не увидите, так как реальный размер контейнера остался неизменным и равен по-прежнему 5!

Ошибки при myInput не будет , так как хоть и размер вектора равен 5, но память дальше еще есть выделенная. Тем не менее, при выводе вектора vost выведутся только первые 5 элементов , так как vost.size() == 5, о чем я и скачал в самом начале: действительный размер ( vost.size() должен быть равен размеру day_us.size() на момент вызова myInput ). В любом случае для решения данной проблемы можно просто откорректировать размеры vost, чтобы он был такой же большой , как и day_us, соответствующим вызовом resize, только на нужный размер.

Добавлено через 4 минуты
Короче, когда крутите такие штуки со стандартными контейнерами, никогда не забывайте, что потенциально можете нарушить целостность контейнера, то есть его внутреннее состояние, что может фатально сказаться на работе контейнера и программы вцелом, например как здесь : вектор vost не знает свой действительный размер(элементов-то вроде и 15, но vost.size() равен 5 ).
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
03.04.2011, 18:25  [ТС]     Забекапить и восстановить вектор из файла #15
Да, всё понятно, оказалось файл создаётся не там, где я этого ожидал.
Один момент,
В любом случае для решения данной проблемы можно просто откорректировать размеры vost, чтобы он был такой же большой , как и day_us, соответствующим вызовом resize, только на нужный размер.
vost.resize(20);
У меня они таким образом зануляются, хотя по документации вроде не должны
Но значения там присутствуют, я это проверил вот так
C++
1
for (int i = 0; i < day_us.size()+10; i++)
Может я ошибаюсь, сейчас попробую изучить этот вопрос подробнее, но если это так, то решения 2,
- либо задавать размер вектора иным способом, при котором элементы не затрагиваются, если такой есть,
- либо сначала делать resize на нужное количество элементов, а потом из файла не добавлять к ним новые, а как-то записывать поверх начиная с первого.
Ma3a
Эксперт C++
612 / 456 / 31
Регистрация: 28.01.2011
Сообщений: 605
03.04.2011, 18:30     Забекапить и восстановить вектор из файла #16
Иного корректного способа нет, лучше всего будет именно сначала позаботиться об исходных размерах вызовом reserve, потом настроить реальный размер вызовом resize( reserve для того, чтобы при последующих resize не было лишних выделений памяти ), а потом писать новые элементы поверх старых.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.04.2011, 18:32     Забекапить и восстановить вектор из файла
Еще ссылки по теме:

Как восстановить список из бинарного файла? C++
C++ Нужно реализовать класс "вектор" с конструкторами, которые позволяют создать нулевой вектор и вектор с произвольным кол-во элементов.
C++ Чтение данных из файла в вектор

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

Или воспользуйтесь поиском по форуму:
Kadet89
2 / 2 / 0
Регистрация: 18.09.2009
Сообщений: 107
03.04.2011, 18:32  [ТС]     Забекапить и восстановить вектор из файла #17
Всё, вопрос закрыт, тема раскрыта полностью, спасибо
Yandex
Объявления
03.04.2011, 18:32     Забекапить и восстановить вектор из файла
Ответ Создать тему
Опции темы

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