С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.88
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
#1

Сериализация и десериализация vector'а int'ов - C++

05.03.2011, 16:26. Просмотров 3372. Ответов 15
Метки нет (Все метки)

Имею вектор:
C++
1
std::vector<int> mig
Нужно очень быстро сохранить его в файл, а потом восстановить из файла, пользуясь тем фактом, что это вектор int'ов. Т.е. не содержет никаких структур и указателей на объекты вне самого вектора. Т.к. вектор находится в едином цельном куске памяти, то задача сводится к простому копированию этого участка памяти в файл. И потом обратно копирование всего файла в память.
Помогите пожалуйста реализовать
Спасибо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.03.2011, 16:26
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Сериализация и десериализация vector'а int'ов (C++):

Сериализация и десериализация структуры - C++
Есть структура с полями string , int. Вся информация пишется в файл.txt, мне нужно сделать сериализацию и десериализацию этого файла. ...

Сериализация и десериализация двусвязного списка - C++
Всем доброго времени суток! Ребят помогите реализовать функции сериализации и десериализации двусвязного списка. Заранее спасибо

Сериализация - C++
Не создаётся тема Добавлено через 11 секунд Привет! Вот код, который записывает в динарник структуру и считывает её оттуда, конечно...

Сериализация - C++
Доброго времени суток,есть пару вопросов по сериализации. 1. Допустим есть некий класс содержащий вектор структур. В программе...

Сериализация - C++
Что-то я не совсем понял сериализацию. Использовать код наподобие MyClass m; std::ofstream f (&quot;dump.bin&quot;, std::binary); ...

сериализация - C++
Нужно записать стек из матриц stack&lt;vector&lt;vector&lt;int&gt; &gt; &gt; в файл, чтобы можно было останавливать и продолжать перебор. Я так понимаю,...

15
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
05.03.2011, 16:33 #2
Union, Я бы просто считал вектор в файл - считал вектор из файла... Не вижу резона делать чего-либо другого...

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
#include <vector>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <string>
 
int main()
{
    std::string f_name;
    std::cout<<"Enter file_name\n";
    std::cin>>f_name;
    std::cout<<"Enter elements of vector. / for end\n";
    std::vector<int> vc((std::istream_iterator<int>(std::cin)), std::istream_iterator<int>());
    std::ofstream ofs(f_name.c_str());
    //Здесь должна бы быть проверка на открытие
    std::copy(vc.begin(), vc.end(), std::ostream_iterator<int>(ofs, "\n"));
    vc.clear();
    ofs.close();
    std::ifstream ifs(f_name.c_str());
    //И тут проверка
    std::cin.clear();
    std::cin.get();
    std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(), std::back_inserter(vc));
    std::copy(vc.begin(), vc.end(), std::ostream_iterator<int>(std::cout, "\n"));
    return 0;
}
1
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
05.03.2011, 17:23  [ТС] #3
Посмотрел данный метод, вектор записывается в файл поэлементно через разделитель \n + каждый элемент конвертируется из int в string. А можно ли как-нибудь записывать в бинарном виде? Нужна максимальная производительность, в приложении постоянно копируются вектора по 500-900 тыс элементов. М.б.можно как-то через memcpy сразу по нескольку элементов копировать?
Спасибо.

Добавлено через 27 минут
Можно ли записывать Int'ы без конвертации в строки? Int = 4 байта - записывать 4 байта и потом считывать по 4 байта. Тогда разделитель \n не нужен. Каждые 4 байта соответствуют одному элементу в векторе.
0
insolent
826 / 344 / 15
Регистрация: 30.01.2009
Сообщений: 1,204
05.03.2011, 18:12 #4
Union, открывай файл для бинарной записи.
0
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
05.03.2011, 19:02  [ТС] #5
Это смао собой Меня интересует реализация алгоритма вцелом. Т.е. не только как записать, но и как потом восстановить. В приведенном примере восстанавливается через разделитель \n. А так надо будет забирать по 4 байта.

Добавлено через 46 минут
C++
1
std::ofstream ofs("2.dat", std::ios::binary);
Вот открыл для бинарной записи.
C++
1
std::copy(vc.begin(), vc.end(), std::ostream_iterator<int>(ofs, "\n"));
всёравно переводит int в строку и записывает через разделитель.
Впринципе разделитель я молгу убрать, но как заставить std::copy записывать int как int, без конвертации?
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
05.03.2011, 19:18 #6
я не силен в данной теме, но соображения
1) если это винда, то с помощью CreateFileMapping спроецировать файл в память с заданием размера
2) первым элементом записать int'ом размер вектора
3) с помощью memcpy записать весь вектор в духе memcpy( base, &v.front(), v.size() * sizeof(int) );

обратные действия понятны
1) открыть также файл для чтения
2) прочитать размер сделать v.resize( .. )
3) с помощью memcpy ( &v.front(), base, v.size() * sizeof(int) )

под линь тоже маппинг делают, но тут уж не просвещен
0
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
05.03.2011, 19:26  [ТС] #7
1) К сожалению это linux (Ubunta)
2) Размер записывать вовсе необязательно, я могу его сохранить отдельно, в базе. В общем вся задача сводится к банальному копированию участка памяти.
3) Я искал возможность через memcpy прямиком скопировать вектор, т.к. при данных условиях по быстродействию это решение было бы оптимальным, а поэлементное копирование, да ещё и спреобразованием - расточительство.
Пока про memcpy ничего не нашёл, жду, может кто здесь подскажет.
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
05.03.2011, 19:31 #8
http://linux.die.net/man/2/mmap
http://www.cplusplus.com/reference/clibrary/cstring/memcpy/
0
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
05.03.2011, 19:35  [ТС] #9
Я в приложении часто использую memcpy с char'ами, но не имею никакого представления насчёт вектора. Мои знания насчёт вектора и stl вообще чисто поверхностные - это принцип работы, что такое итераторы и т.д. В общем я не знаю как применить memcpy в этой задаче...
0
igorrr37
1648 / 1276 / 133
Регистрация: 21.12.2010
Сообщений: 1,932
Записей в блоге: 7
05.03.2011, 19:37 #10
читает и пишет блок памяти вроде как
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <vector>
#include <fstream>
#include <iostream>
 
int main(){
    std::vector<int> v={1,2,3,4,5,6}, res(10);
    std::ofstream ofs("1.dat", std::ios::binary);
    ofs.write(reinterpret_cast<char*>(&v[0]), v.size()*4);
    ofs.close();
    std::ifstream ifs("1.dat", std::ios::binary);
    if(!ifs){std::cerr<<"File not found"; return 1;}
    ifs.read(reinterpret_cast<char*>(&res[0]), res.size()*4);
    for(int i=0; i<res.size(); i++){
        std::cout<<res[i]<<"  ";
    }
    ifs.close();
}
1
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
05.03.2011, 19:46  [ТС] #11
igorrr37 спасибо за пример, но опять же лишние операции используются...
Вот я нашел темы про копирование вектора через memcpy:
std::vector<>::iterator в VS6 и VS2008
http://en.wikipedia.org/wiki/Std::vector
http://bytes.com/topic/c/answers/849132-std-vector-c-array
Помогите применить
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
05.03.2011, 19:57 #12
Union, я писал уже как копировать, однакож кто читает?
Цитата Сообщение от novi4ok Посмотреть сообщение
::memcpy (int_buf, &*int_vect.begin(), sizeof(int)*2);
дикий угар на самом деле
0
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
05.03.2011, 20:22  [ТС] #13
alex_x_x извиняюсь, зациклился на записи, поэтому не стал читать после "обратные действия понятны"
Тем неменее в тех темах более полный код.
Мне уже кажется что записать в файл через memcpy по некоторым причинам не возможно...

Добавлено через 18 минут
Если это возможно, должно быть как-то так:
C++
1
2
3
4
     std::vector<uint32_t> v1;
     // Заполняем вектор
     std::ofstream ofs("2.dat", std::ios::binary);
     memcpy( &*v1.begin(), ofs, 1024 );
Само сабой это не работает.
И помоему копировать в дескриптор через memcpy некорректно...Наверно нужно использовать промежуточный буфер, который будет заполняться через memcpy, а далее уже через std::copy закидывать его в файл.
Я прав?
0
igorrr37
1648 / 1276 / 133
Регистрация: 21.12.2010
Сообщений: 1,932
Записей в блоге: 7
05.03.2011, 20:49 #14
Union, какие ещё лишние операции?
reinterpret_cast<char*>(&v[0]) - приведение указателей. В memcpy будет неявное приведение к void*;
v.size()<<2 - вычисление размера vector<int> в байтах, для memcpy это тоже потребуется
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
05.03.2011, 21:02 #15
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
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iterator>
 
int main()
{ 
  std::vector< int > v;
  for( int i=0;i<10;++i )
    v.push_back( i );
  int length = v.size() * sizeof( int );
 
  int fd = open( "1.txt", O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600 );
  if( -1 == fd )
    {
      perror( "cant open file" );
      return -1;
    }
  if( -1 == ftruncate( fd, length ) )
    {
      perror( "cant truncate file" );
      return -1;
    }
  void* base = mmap( 0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
  if( MAP_FAILED == base )
    {
      perror( "cant mapped file" );
      return -1;
    }
  memcpy( base, &v.front(), length );
  if( -1 == munmap( base, length ) )
    {
      perror( "error unmapping file" );
    }
  close( fd );
  v.clear();
 
  //unserialize file
  fd = open( "1.txt", O_RDWR, (mode_t)0600 );
  if( -1 == fd )
    {
      perror( "cant reopen file" );
      return -1;
    }
 
  base = mmap( 0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
  if( MAP_FAILED == base )
    {
      perror( "cant remapped file" );
      return -1;
    }
 
  v.resize( length / sizeof(int) );
  memcpy( &v.front(), base, length );
  
  std::copy( v.begin(), v.end(), std::ostream_iterator<int>( std::cout, " " ) );
  if( -1 == munmap( base, length ) )
    {
      perror( "error unmapping file" );
    }
  close( fd );
  
}
даже работает

Добавлено через 11 минут
igorrr37, все хорошо, но
Цитата Сообщение от igorrr37 Посмотреть сообщение
v.size()*4
плохо, v.size() * sizeof( int )
int разным по размеру бывает
1
05.03.2011, 21:02
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.03.2011, 21:02
Привет! Вот еще темы с ответами:

Сериализация - C++
есть небольшая программа вот структура данных которая в ней используется class table { public: int number,kol,year; ...

Сериализация - C++
Мне нужно записать объект в файл и считывать из файла в объект. Используя при этом перегрузку операторов файлового в\в (ifstream и...

Потоки, сериализация - C++
Подскажите хороший источник где можно найти нормальную информацию по данным темам. Гугл предлогать не стоит) 1) Приоритет потока....

Сериализация данных - C++
Появилась новая проблема. Создаю объект и записываю его в файл через одну функцию: mammal obj(m_s, t_s, s, vod, r, d, v); ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

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