Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Как записать vector в файл  (Прочитано 57234 раз)
0 Пользователей и 1 Гость смотрят эту тему.
zz
Гость
« : 27-06-2006 19:51 » 

У меня вопрос:
Всю жизнь писал на простом C (stdio, fopen, fread и т.п.), решил переходить на C++ - STL.

Имею vector <char> vect;
Требуется сохранить его в файл (в любом формате, например, двоичном, чтобы можно было его потом загрузить обратно).
Как это грамотно сделать? (Через ofstream или еще как-нибудь).
file << vect; - не работает - пишет:
'operator<<' not implemented in type 'ofstream' for arguments of type 'vector<char,allocator<char> >'

Хотелось бы как-нибудь сделать это быстро - за одну операцию записи.
« Последнее редактирование: 06-12-2007 18:45 от Алексей1153++ » Записан
Sands
Помогающий

ua
Offline Offline

« Ответ #1 : 27-06-2006 20:02 » 

По моему, тут так просто не будет. Скорей всего только поелементная запись либо по индексу либо через итератор.
Записан
zz
Гость
« Ответ #2 : 27-06-2006 20:22 » new

Тогда вопрос:
А как лучше всего решать эту задачу?
Надо работать с массивом, длина которого изначально неизвестна.
Кроме того его требуется сохранять в файле / загружать из файла.
Это что же, надо как раньше, char *vect; / malloc / realloc / fread / fwrite?
Есть ли способ проще (например, в C++ есть что-нибудь для этого)?
Записан
Sands
Помогающий

ua
Offline Offline

« Ответ #3 : 27-06-2006 21:23 » 

Можно и как раньше, но можно и вектор использовать. А при записи можеш либо в цикле по вектору бежать
Код:
vector<char> Str;
....
for(int i=0;i<Str.size();i++)
 {
   file<<Str[i];
 }
или можеш перед записью выделить кусок памяти по текущему размеру вектора, перегнать туда все елементы вектора, а потом через fwrite писать их в файл.
P.S. По-моему ты не там пытаешся економить. Операции чтения/записи в подобного рода задачах надо делать в лоб. Хотя если кто даст метод получше буду только благодарен
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 28-06-2006 07:27 » 

Во-первых, malloc и free не стоит использовать - есть new и delete, которые помимо выделения памяти ещё вызывают и конструктор с деструктором.

Во-вторых, realloc тоже не надо использовать. vector имеет переменный размер в run-time, и через push_back, pop_back и другие его методы можно добавлять в него новые элементы. Соответственно, можно и удалять элементы.

В-третьих, при работе с файлами лучше использовать потоки ifstream и ofstream, работа с которыми аналогична работе с cin, cout.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
zz
Гость
« Ответ #5 : 28-06-2006 15:05 » 

realloc тоже не надо использовать. vector имеет переменный размер в run-time
Так я об этом и говорю, именно поэтому я и хотел использовать vector.

при работе с файлами лучше использовать потоки ifstream и ofstream, работа с которыми аналогична работе с cin, cout.
В этом, собственно, и заключался первоначальный вопрос:

Хотелось бы как-нибудь сделать это быстро - за одну операцию записи.
IMHO делать это в цикле по одному байту - не самое оптимальное решение по скорости
Записан
acc15
Гость
« Ответ #6 : 28-06-2006 15:50 » 

Я что-то не пойму...
Разве fwrite(vect,vect.size(),0,f); не прокатит?... зачем обязательно использовать STL когда в каких то вариантах и старые добрые RTL функции намного лучше?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 28-06-2006 15:54 » 

Цитата: zz
IMHO делать это в цикле по одному байту - не самое оптимальное решение по скорости
Откуда такое мнение? Файловые операции уже лет 20, если не более, обычно буферизируются. Записать в файловый поток не означает вызывать движение головок диска и ожидание программы. Файловые потоки имеют манипуляторы flush (сброс буфера на диск), endl (конец строки и автоматический flush), а также сбрасывают буфера при своём закрытии. Операция << вывода в поток не является записью на диск, а является записью в буфер потока. Сброс буфера на диск реализуется как блочная операция. Если же речь идёт о современных HD, то они имеют встроенные кэши мегабайтных размеров.

Далее, исполнение операции записи outfilestream << vec может быть реализовано через перегрузку оператора << потока. Однако такая реализация внутри всё равно содержит цикл. Считать, что, если программист в своём коде видит не цикл, а  вызов фукции, такая операция быстрее явного цикла в коде - это самообман.
« Последнее редактирование: 28-06-2006 16:02 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 28-06-2006 16:00 » 

Цитата: acc15
Я что-то не пойму...
Разве fwrite(vect,vect.size(),0,f); не прокатит?... зачем обязательно использовать STL когда в каких то вариантах и старые добрые RTL функции намного лучше?
Что-то я не пойму... Вы об ООП представление имеете?

Вектор - это объект. Занимаемая им память не есть прямое хранилище чисел типа массива. Размер объекта vector и vector.size() - это разные количества, более того, несопоставимые. К тому же содержимое объекта не обязательно хранится как последовательный участок памяти, а может быть, например, списком адресов на внутренние объекты, расположенные в памяти где угодно.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
acc15
Гость
« Ответ #9 : 28-06-2006 16:06 » 

Цитата
Считать, что, если программист в своём коде видит не цикл, а  вызов фукции, такая операция быстрее явного цикла в коде - это самообман.
Есть исключения... - memcpy,memset и т.д. и это не самообман... т.к. на ассемблере под конкретную платформу... Доли секунд, но всё же это уже не самообман. А если требуется сделать миллионы memcpy? это уже 1-2 секунды.
Цитата
Вектор - это объект. Занимаемая им память не есть прямое хранилище чисел типа массива. Размер объекта vector и vector.size() - это разные количества, более того, несопоставимые. К тому же содержимое объекта не обязательно хранится как последовательный участок памяти, а может быть, например, списком адресов на внутренние объекты.
Это я знал когда Hello world писал. STL сам не пользуюсь, т.к. имею собств. классы для таких целей, которые сделаны т.к. мне удобнее... Поэтому такая вот ошибочка вышла =)
Но вообще мне кажется что речь идет именно о массиве, а не о классе "vector". Если я не прав, то кроме как именно побайтовой записи в файл другого варианта нету, т.к. данные дефрагментированы в памяти.
« Последнее редактирование: 28-06-2006 16:16 от acc15 » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 28-06-2006 16:17 » 

Цитата
Есть исключения... - memcpy,memset и т.д. и это не самообман... т.к. на ассемблере под конкретную платформу... Доли секунд, но всё же это уже не самообман. А если требуется сделать миллионы memcpy? это уже 1-2 секунды.
Если на уровне железа поддерживаются блочные операции, то да. Но речь идёт о вполне прикладной задаче, причём о её реализации на таком высоком уровне, что на уровне исходного кода последовательная или блочная работа железа явно не выражается, да и не должна выражаться. Специфика платформы в описании задачи не указана, следовательно, решение должно быть универсальным.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
zz
Гость
« Ответ #11 : 28-06-2006 18:17 » 

Что касается исходного вопроса 

Пока сделал так же, как и всегда (на чистом C):

Вот это - в основном цикле (в принципе, одна строчка):
Код:
            if(vectsize%1024==0)vect=(char *)realloc(vect,vectsize+1024);
// . . .
            vectsize++;
При этом запись в файл:
Код:
                    if(fwrite(vect,1,vectsize,out)!=vectsize)
                        sprintf(statemsg,"Невозможно записать в файл с именем %s",filename);



Если писать это на STL/C++ (этот код пишу из головы, но по-моему, должно быть так):
Код:
            if(vectsize%1024==0)vect.resize(vectsize+1024);
Запись в файл (в принципе, тоже одна строчка):
Код:
vector<char> Str;
....
for(int i=0;i<Str.size();i++)
 {
   file<<Str[i];
 }

Просто как-то возиться с realloc надоело, но получается C++ ничего более простого предложить не может Не понял
Код упростился примерно настолько же, насколко и усложнился.
Вопрос:
Посоветуйте, можно ли как-нибудь проще - необязательно через STL.
Пока думаю насчет AnsiString, но у меня, вообще говоря, двоичные данные, может быть и '\0' и вообще не знаю, поможет ли  Здесь была моя ладья...



Что касается побайтовой работы с файлами:
Действительно, разница не столь велика, как я думал  Улыбаюсь
Вот это копирует файл 700 Mb (побайтово) за 1мин 42 сек:
Код:
int main(int argc, char* argv[])
{
if(argc!=3)return 1;
char c;
ifstream i(argv[1],ios::in |ios::binary);
ofstream o(argv[2],ios::out|ios::binary);
while(i.get(c))o.put(c);
return 0;
}

А вот это - файл 696 Mb (блоками) - за 1 мин 05 сек:
Код:
int main(int argc, char* argv[])
{
char buf[2048];
int size;
FILE *i,*o;
if((i=fopen(argv[1],"rb"))==NULL)return 1;
if((o=fopen(argv[2],"wb"))==NULL)return 1;
while((size=fread(buf,1,2048,i))!=0)fwrite(buf,1,size,o);
return 0;
}

Вообще я раньше проводил подобные эксперименты (только побайтово - через fgetc/fputc) - скорость отличалась в 5-10 раз. Быть такого не может

P.S: Но основной вопрос все-таки в том, как грамотно работать с массивом (или вектором, или еще не знаю чем) и при этом легко сохранять его на диск.
« Последнее редактирование: 06-12-2007 18:46 от Алексей1153++ » Записан
acc15
Гость
« Ответ #12 : 28-06-2006 18:28 » 

Всё же определись: с массивом или классом vector?
как варианты могу предложить наследование класса vector добавив ф-ции сохранения/загрузки в/из файл(а)...
А вообще смотря что тебе надо... Если нужна производительность забудь про vector...
« Последнее редактирование: 28-06-2006 18:34 от acc15 » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 28-06-2006 18:32 » 

Может проще описать свою задачу, чтобы отвечающим было понятно, что вообще требуется сделать?

Как работать с векторами и потоками, уже объяснялось. А вот это стремление вставить блочные операции совершенно непонятно. В STL есть классы работы с массивами, обеспечивающие максимальную производительность за счёт снижения удобства работы с ними. Но всякий класс надлежит применять в соответствии с решаемой задачей. Задача же в данном случае неопределена.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
zz
Гость
« Ответ #14 : 28-06-2006 19:03 » 

Прошу прощения, по ходу обсуждения вопрос немного переформулировался:
Задача:
Хранить большое количество (изначально неизвестное) чисел (в диапазоне от -128 до 127), которые поступают в процессе работы программы.
При этом необходимо иметь произвольный доступ к каждому прочитанному ранее числу.
Кроме того, необходимо в некоторый момент записать все эти числа в файл.
А в некоторый другой момент - прочитать из файла.

Какие я вижу пути решения:
1. Использовать указатель char * (он же массив)
Недостаток: потребуестя периодически менять размер выделенной под него памяти, т.е. делать realloc.

2. Использовать vector
Недостаток: неудобно сохранять его в файл (надо делать цикл).

3. Искать другие пути
Пока не знаю, что: другие классы C++ или еще что-нибудь

Вопрос: Какой из вариантов на Ваш взгляд кажется лучше, что можно сделать с недостатками (в п. 1, 2), или какие Вы видите другие пути?
Записан
acc15
Гость
« Ответ #15 : 28-06-2006 20:09 » 

Моё решение. Работай как с обычным массивом. Для изменения длины - SetLength (GetLength - понятно для чего) Возможно аналог данного класса есть и в стандартных библиотеках, но увы... на поиск и изучение работы с ним уйдет больше времени чем сделать свой...

Код:
template <class T> class c_Array {

protected:
T *pPtr;
unsigned long nCount;

void Initialize()
{
pPtr = 0;
nCount = 0;
}

public:

c_Array()
{
Initialize();
}
c_Array(unsigned long nCount)
{
Initialize();
SetLength(nCount);
}
c_Array(const c_Array &arr)
{
Initialize();
Copy(arr);
}
~c_Array()
{
SetLength(0);
}
bool SetLength(unsigned long nNewCount,bool bDoResize = true)
{
if (nCount == nNewCount) return true;

if (nNewCount == 0) {

if (pPtr)
{
delete [] pPtr;
pPtr = 0;
}

} else {

if (pPtr) {

T* pNewPtr = new T[nNewCount];
if (!pNewPtr) return false;
if (bDoResize)
for (unsigned long i=0;i<nCount && i<nNewCount;i++)
pNewPtr[i] = pPtr[i];
pPtr = pNewPtr;

} else {

pPtr = new T[nNewCount];
if (!pPtr) return false;

}

}
nCount = nNewCount;
return true;
}
unsigned long GetLength(void)
{
return nCount;
}

bool Add(T& item)
{
if (!SetLength(nCount+1)) return false;
pPtr[nCount-1] = item;
return true;
}
bool Insert(unsigned long nPos,const T& item)
{
if (nPos > GetLength()) return false;

T* pNewPtr = new T[nCount+1];
if (!pNewPtr) return false;

unsigned long i;
for (i=0;i<nPos;i++) pNewPtr[i] = pPtr[i];
pNewPtr[nPos] = item;
for (i=nPos+1;i<nCount+1;i++) pNewPtr[i] = pPtr[i-1];

if (pPtr) delete [] pPtr;
pPtr = pNewPtr;
nCount++;

return true;
}
bool Remove(const unsigned long index)
{
if (index >= nCount) return false;

if (nCount > 1) {
T* pNewPtr = new T[nCount-1];
unsigned long i;
for (i=0;i<index;i++) pNewPtr[i] = pPtr[i];
for (i=index+1;i<nCount;i++) pNewPtr[i-1] = pPtr[i];

delete [] pPtr; pPtr = pNewPtr;
nCount--;
return true;
} else return SetLength(0,false);
}
bool CopyFrom(const T* source,const unsigned long count)
{
if (!source || !count) return false;

for (unsigned long i=0;i<min(nCount,count);i++) pPtr[i] = source[i];
return true;
}
bool CopyTo(T* dest) const
{
if (!dest) return false;

for (unsigned long i=0;i<nCount;i++) dest[i] = pPtr[i];
return true;
}

void SetAll(const T& item)
{
for (unsigned long i=0;i<nCount;i++) pPtr[i] = item;
}
bool Set(const unsigned long index,const T& item)
{
if (index>=nCount) return false;

pPtr[index] = item;
return true;
}
const T& Get(unsigned long index) const
{
if (index>=nCount) return pPtr[0];

return pPtr[i];
}
bool Copy(const c_Array& x)
{
if (!SetLength(x.nCount,false)) return false;
if (!CopyFrom(x.pPtr,x.nCount)) return false;
return true;
}
operator T*()
{
return pPtr;
}
c_Array& operator=(const c_Array& x)
{
Copy(x);
return *this;
}
};

т.е. пример который тебя конкретно интересует:

запись:
Код:
c_Array <char> abc(10); // 10 - размер изначально

abc.Add('X');
abc.Add('Y');
abc.Add('Z');
fwrite(abc,sizeof(char),abc.GetLength(),file);


или по другому
ЗЫ: лучше используй что было раньше =)

Код:
abc.SetLength(abc.GetLength()+1);
abc[abc.GetLength()-1] = 'X';
abc.SetLength(abc.GetLength()+1);
abc[abc.GetLength()-1] = 'Y';
abc.SetLength(abc.GetLength()+1);
abc[abc.GetLength()-1] = 'Z';
fwrite(abc,sizeof(char),abc.GetLength(),file);

чтение:

Код:
abc.SetLength(размер который нужен, к примеру размер файла);
fread(abc,sizeof(char),abc.GetLength(),file);

Или другой вариант - наследование этого же класса:
Код:
template <class T> class c_FileArray : public c_Array <T>
{

public:
   long WriteToFile(FILE *f) {
      return fwrite(pPtr,sizeof(T),nCount,f);
   }
   long ReadFromFile(FILE *f)
   {
      return fread(pPtr,sizeof(T),nCount,f);
   }
};

дальнейшее использование:

запись:
Код:
c_FileArray <char> farray;
...
farray.Add('x');
farray.Add('y');
farray.Add('z'); // Добавляем некоторое количество...
farray.WriteToFile(file); // записываем в файл
...

чтение:
Код:
...
c_FileArray <char> farray;

farray.SetLength(кол-во элементов которое нужно будет считать из файла);
farray.ReadFromFile(file);
...

или можно сделать операторами, тогда использовать можно именно так как ты хотел изначально:
Код:
template <class T> class c_FileArray : public c_Array <T>
{

public:
   long operator>>(FILE *f) {
      return fwrite(pPtr,sizeof(T),nCount,f);
   }
   long operator<<(FILE *f)
   {
      return fread(pPtr,sizeof(T),nCount,f);
   }
};

т.е. дальше можно так:

Код:
abc >> file; // запись
abc << file; // чтение

и без i(o)fstream ов =)
Вот собственно и всё...
« Последнее редактирование: 06-12-2007 18:47 от Алексей1153++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 28-06-2006 21:07 » 

zz, Каковы требования к быстродействию? Что значит "большое количество"? Какое максимально допустимое значение?

acc15, есть такое понятие, как повторное использование кода. Собственно поэтому STL предпочтительнее самописных решений. Объяснять почему - не в этой теме. Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
acc15
Гость
« Ответ #17 : 28-06-2006 21:13 » 

интересно почему же они забыли про >> и << для файлов? =) найди ка мне такой вариант в твоём любимом STL
Записан
zz
Гость
« Ответ #18 : 28-06-2006 22:10 » 

acc15,
Спасибо за код, однако думаю, что fwrite работать не будет по той же причине:
Вектор - это объект. Занимаемая им память не есть прямое хранилище чисел типа массива. Размер объекта vector и vector.size() - это разные количества, более того, несопоставимые. К тому же содержимое объекта не обязательно хранится как последовательный участок памяти, а может быть, например, списком адресов на внутренние объекты, расположенные в памяти где угодно.
Т.к. pPtr - это указатель.
Хотя, конечно, перегрузить операторы <<, >> для обращения к pPtr - проблем нет. Улыбаюсь

dimka,
Прошу прощения, если отвлекаю вопросами не по существу - особо жестких требований к быстродействию нет.
Просто хочу, чтобы программа была написана хорошим силем, а создавать циклы там, где можно без них обойтись (тем более в ущерб производительности) - IMHO не есть хороший стиль программирования.
Ориентировочно (с большим запасом) максимально допустимое количество - 100 000. Во всяком случае - точно в пределах разрядности int.
Хотя, конечно, проще всего было бы написать: char vector[100000]; и не напрягаться, но это IMHO тоже не есть хороший стиль программирования.

Вообще как-то не верится, что в C++ нет стандартных (или почти стандартных) средств для подобных задач - вроде бы, задача довольно естественная Здесь была моя ладья...
Записан
acc15
Гость
« Ответ #19 : 28-06-2006 22:26 » 

zz, а может стоит попробовать ? =) Вдруг случайно заработает... так невзначай =)
И я в примере не vector наследовал, так что он тут вообще не причем... читай внимательнее... pPtr указатель именно на массив а не вектор и данные массива идут в памяти последовательно...

Стандартных средств лично я не знаю... Но не проще ли написать своё раз и навсегда?
« Последнее редактирование: 28-06-2006 22:33 от acc15 » Записан
zz
Гость
« Ответ #20 : 28-06-2006 23:08 » 

acc15, извинения, я был неправ  Улыбаюсь
Действительно, здесь: "fwrite(abc,sizeof(char),abc.GetLength(),file);" вызывается "operator T*()", который возвращает pPtr;
А не работало бы это (вернее, не так работало) в случае "fwrite(&abc,sizeof(char),abc.GetLength(),file);"
Записан
Anchorite
Гость
« Ответ #21 : 29-06-2006 02:40 » 

Ну вы, блин, даете. Ага
Пример для вестора из char.

Код:
// Пишем
file.write(&vect[0], sizeof(char) * vect.size());

// Читаем (vectSize - число элементов читаемых из потока)
vect.resize(vectSize);
file.read(&vect[0], sizeof(char) * vectSize)

Но сразу же предупрежу - данный способ работает только для встроенных типов.
Для каких-то самописных классов он не пойдет.
« Последнее редактирование: 29-06-2006 02:41 от Anchorite » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 29-06-2006 06:36 » 

Цитата: zz
Прошу прощения, если отвлекаю вопросами не по существу - особо жестких требований к быстродействию нет.
Просто хочу, чтобы программа была написана хорошим силем, а создавать циклы там, где можно без них обойтись (тем более в ущерб производительности) - IMHO не есть хороший стиль программирования.
Так я и думал. Улыбаюсь Хороший стиль - это не писать того, чего не требуется, и писать как можно меньше кода без ущерба для архитектуры. Что же касается производительности, то существуют понятия "микрооптимизации" и "макрооптимизации". При этом многие полагают, что первое губит второе. Т.е. код, оптимизированный по скорости исполнения, становится нечитабельным и плохо модифицируемым.

100 000 int - это на 32-хбитной платформе 400 000 байт - меньше полумегабайта. Для десктопов или серверов, память которых измеряется уже гигабайтами, пытаться экономить байты - это пустая трата времени. Для других устройств полмегабайта может быть существенным размером, и там в самом деле нужна оптимизация. "Много" у разных людей имеет разное значение. У нас, например, люди системы многоканального видеонаблюдения делают, так их хоть байтовые, хоть блочные операции записи на диск не устраивают - тормозят файловые системы, поэтому работают с "сырым" диском - увеличение производительности примерно в 2-3 раза. Объёмы данных, естественно, десятки гигабайт.

Организовывать блочную запись, где размер блока подогнан под размер дискового кластера - это, конечно, увеличение быстродействия. Однако такое решение привязывает программу к конкретному диску или классу дисков. На других дисках/разделах/файловых системах эта "оптимизация" не сработает, а, может быть, даже будет источником падения производительности. Хорошее решение - это решение, универсальность или специальность которого соотнесены с задачами программы.

Цитата: zz
Вообще как-то не верится, что в C++ нет стандартных (или почти стандартных) средств для подобных задач - вроде бы, задача довольно естественная.
В общем случае задача сериализации объектов не так тривиальна, как может казаться.

Anchorite, да, где-то уже обсуждался вопрос о том, что vector из STL хранит данные последовательно. Правда, из того обсуждения я так и не понял, является ли это требованием стандарта или особенностью компиляторов на распространённых платформах. Поэтому я на всякий случай подобных решений не предлагаю. Улыбаюсь

Пример из MSDN:
Код:
// ios_streamsize.cpp
// compile with: /EHsc
#include <iostream>
#include <fstream>

int main( )
{
   using namespace std;
   char a[16] = "any such text";
   ofstream x( "test.txt" );
   streamsize y = 6;
   x.write( a, y );
}
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Anchorite
Гость
« Ответ #23 : 29-06-2006 15:31 » 


Anchorite, да, где-то уже обсуждался вопрос о том, что vector из STL хранит данные последовательно. Правда, из того обсуждения я так и не понял, является ли это требованием стандарта или особенностью компиляторов на распространённых платформах. Поэтому я на всякий случай подобных решений не предлагаю. Улыбаюсь

Это требование стандарта ISO/IEC 14882 Second edition 2003-10-15.
Все компиляторы, с которыми я на настоящий момент работаю (MinGW GCC 3.4.2 и MSVS .NET 2005) ему соответствуют.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 29-06-2006 16:21 » 

Anchorite, а более ранних? Далеко не все ещё используют GCC 3.4.2 или VC++ 2005.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Anchorite
Гость
« Ответ #25 : 30-06-2006 02:33 » 

Не могу сказать ничего определенного. Жаль
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #26 : 03-07-2006 17:50 » 

Добрый день!
Используй BOOST::SERIALIZE и будет тебе счастье. На сайте, www.boost.org есть пример с записью в файл. vectora сериализуются автоматически.
Записан

Странно всё это....
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #27 : 04-07-2006 18:42 » 

Добрый день!
Используй BOOST::SERIALIZE и будет тебе счастье. На сайте, www.boost.org есть пример с записью в файл. vectora сериализуются автоматически.
Ладно согласен фигню сморозил Улыбаюсь

проше использовать алгоритм copy получающий итераторы начала и конца вектора плюс итератор от ostream
или воспользоватся тем фактом что вектор гарантированно один не прерывный блок данных и сохранить его соотвествующем образом
Записан

Странно всё это....
LP
Помогающий

ru
Offline Offline

« Ответ #28 : 04-07-2006 19:58 » 

проше использовать алгоритм copy получающий итераторы начала и конца вектора плюс итератор от ostream
Я тоже за этот вариант. Улыбаюсь
Код:
void serialize(const std::string& filename, const std::vector<int>& vec)
{
std::ofstream file(filename.c_str());
std::ostream_iterator<int> beg(file, " ");
std::copy(vec.begin(), vec.end(), beg);
}

void deserialize(const std::string& filename, std::vector<int>& vec)
{
std::ifstream file(filename.c_str());
std::istream_iterator<int> beg(file), end;
std::copy(beg, end, std::back_inserter(vec));
}

Anchorite, а более ранних? Далеко не все ещё используют GCC 3.4.2 или VC++ 2005.
Можно установить STL поновее.

PS Кстати, Anchorite, sizeof(char) всегда 1.  Ага
Записан

Если эта надпись уменьшается, значит ваш монитор уносят
Anchorite
Гость
« Ответ #29 : 05-07-2006 02:27 » 

PS Кстати, Anchorite, sizeof(char) всегда 1.  Ага

Конечно 1 Улыбаюсь
Просто я привел пример в общем виде, что бы было понятнее Улыбаюсь
Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines