STL: банальный вопрос
От: Аноним  
Дата: 22.08.03 10:24
Оценка:
Как наилучшим образом считать файл (ifsream ) в буффер ( vector<char>)?
Re: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 22.08.03 10:39
Оценка: 13 (3)
Здравствуйте, Аноним, Вы писали:

А>Как наилучшим образом считать файл (ifsream ) в буффер ( vector<char>)?



#include <fstream>
#include <vector>

int main()
{
    std::ifstream f("test.txt", std::ios::in | std::ios::binary);

    if( !f )
        return 1;

    std::vector<char> buffer;
    std::ifstream::pos_type size = 0;

    if( f.seekg(0, std::ios::end) )
    {
       size = f.tellg();
    }

    if( size && f.seekg(0, std::ios::beg) )
    {
       buffer.resize(size);
       f.read(&buffer[0], size);
    }
    
    return 0;
}
Re: STL: банальный вопрос
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 22.08.03 10:49
Оценка: 11 (4) +2
Здравствуйте, Аноним, Вы писали:

А>Как наилучшим образом считать файл (ifsream ) в буффер ( vector<char>)?


может так?

ifstream inputFile("filename.txt");
vector<char> filedata( ( istreambuf_iterator<char>( inputFile ) ), istreambuf_iterator<char>() );
Re: вопрос
От: Аноним  
Дата: 27.08.03 10:00
Оценка:
    std::vector<char> buf;
    std::ifstream inputFile("name.txt");
    std::copy(std::istreambuf_iterator<char>(inputFile),
             std::istreambuf_iterator<char>(),
    std::back_inserter(buf));


хоть я и использую это код, но не понимаю, как он работает.
не может же std::istreambuf_iterator<char>() указывать на конец файла.
может кто обьяснит.
спасибо
Re[2]: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 27.08.03 10:26
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, Аноним, Вы писали:


А>>Как наилучшим образом считать файл (ifsream ) в буффер ( vector<char>)?


OE>может так?


OE>
OE>ifstream inputFile("filename.txt");
OE>vector<char> filedata( ( istreambuf_iterator<char>( inputFile ) ), istreambuf_iterator<char>() );
OE>


VC6 этот код не компилирует

example.cpp
D:\WORK\test2\example.cpp(846) : error C2664: '__thiscall std::vector<char,class std::allocator<char> >::std::vector<char,class std::allocator<char> >(unsigned int,const char &,const class std::allocator<char> &)' : cannot convert parameter 1 from '
class std::istreambuf_iterator<char,struct std::char_traits<char> >' to 'unsigned int'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called




Хочу сравнить эффективность своего варианта с предложенным. Не сочтите за труд. Пусть входной файл будет в 1Mb.
Re[3]: STL: банальный вопрос
От: Lorenzo_LAMAS  
Дата: 27.08.03 10:33
Оценка:
Это потому, что в старом динкумваровском стле не было конструкоров member-template
Of course, the code must be complete enough to compile and link.
Re[2]: вопрос
От: Lorenzo_LAMAS  
Дата: 27.08.03 10:39
Оценка:
А>не может же std::istreambuf_iterator<char>() указывать на конец файла.

Ээээ, в реализации, которую я смотрел, там есть указатель. Когда ты говоришь — std::istream_iterator<char>eos_it; то этот указатель инициализируется нулем. Есть еще, допустим, std::istream_iterator<char>start_it(stream_name); тут указатель инициализирован как надо. Так вот, при разыменовании итератора *start_it (поправят, если не так) проверяется, конец это файла или нет и если да, то указатель устанавливается в 0 (такая же проверка осущ. и при инициализации итератора), а потом итераторы сравниваются и цикл завершается.
Of course, the code must be complete enough to compile and link.
Как наилучшим образом считать файл в буфер?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 27.08.03 11:21
Оценка: 26 (6) +1 -1
#Имя: FAQ.cpp.stl.file2vector
АШ>Хочу сравнить эффективность своего варианта с предложенным. Не сочтите за труд. Пусть входной файл будет в 1Mb.

vc71, release, оптимизация по скорости.

// file2vect.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <vector>
#include <iostream>
#include <fstream>

using namespace std;

int _tmain( int argc, _TCHAR* argv[] )
{
    DWORD t1 = GetTickCount();

    ifstream inputFile( "E:\\PROJECTS\\VC71\\tests\\file2vect\\filename.txt", ios::in | ios::binary );

    if( !inputFile )
    {
        cout << "file open error!!!" << endl;
        return 1;
    }

    vector<char> filedata( ( istreambuf_iterator<char>( inputFile ) ),  istreambuf_iterator<char>() );

    DWORD t2 = GetTickCount();

    cout<< "vector size = " << filedata.size() << ", loading time  = " << t2 - t1 << " ms." << endl;

    return 0;
}


вывод, несколько запусков:

vector size = 2027953, loading time  = 211 ms.
vector size = 2027953, loading time  = 210 ms.
vector size = 2027953, loading time  = 210 ms.
vector size = 2027953, loading time  = 211 ms.


второй вариант:

// file2vect2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <time.h>

using namespace std;

int main()
{
    DWORD t1 = GetTickCount();

    std::ifstream f("E:\\PROJECTS\\VC71\\tests\\file2vect\\filename.txt", std::ios::in | std::ios::binary);

    if( !f )
    {
        cout << "file open error!!!" << endl;
        return 1;
    }

    std::vector<char> buffer;
    std::ifstream::pos_type size = 0;

    if( f.seekg(0, std::ios::end) )
    {
       size = f.tellg();
    }

    if( size && f.seekg(0, std::ios::beg) )
    {
       buffer.resize(size);
       f.read(&buffer[0], size);
    }
    
    DWORD t2 = GetTickCount();

    cout<< "vector size = " << buffer.size() << ", loading time  = " << t2 - t1 << " ms." << endl;

    return 0;
}


вывод, несколько запусков:

vector size = 2027953, loading time  = 20 ms.
vector size = 2027953, loading time  = 10 ms.
vector size = 2027953, loading time  = 20 ms.
vector size = 2027953, loading time  = 10 ms.


с чем вас и поздравляю

на больших файлах различия несколько сглаживаются:

E:\PROJECTS\VC71\tests\file2vect\file2vect\Release\file2vect.exe
vector size = 322525944, loading time  = 88187 ms.

E:\PROJECTS\VC71\tests\file2vect\file2vect2\Release\file2vect2.exe
vector size = 322525944, loading time  = 37514 ms.
Re[4]: STL: банальный вопрос
От: MaximE Великобритания  
Дата: 27.08.03 13:31
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>Хочу сравнить эффективность своего варианта с предложенным. Не сочтите за труд. Пусть входной файл будет в 1Mb.


OE>vc71, release, оптимизация по скорости.


OE>
OE>// file2vect.cpp : Defines the entry point for the console application.

[]

OE>    vector<char> filedata( ( istreambuf_iterator<char>( inputFile ) ),  istreambuf_iterator<char>() );

[]

OE>


На мой взгляд, пример этот слишком экстремален. Редко встречается, когда в пустой вектор с capacity() == 0 читают файл неизвестного размера.

Лично я, когда читаю небольшой файл, то делаю reserve() с запасом. А большие файлы, когда важна производительность, лучше отображать.
Re[5]: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 27.08.03 14:30
Оценка:
ME>На мой взгляд, пример этот слишком экстремален. Редко встречается, когда в пустой вектор с capacity() == 0 читают файл неизвестного размера.

ME>Лично я, когда читаю небольшой файл, то делаю reserve() с запасом.


Мне кажется странным выделять память с запасом при вполне "известном" размере файла. Во всяком случае, есть все средства для его вычисления.
Re[6]: STL: банальный вопрос
От: MaximE Великобритания  
Дата: 27.08.03 14:42
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Мне кажется странным выделять память с запасом при вполне "известном" размере файла. Во всяком случае, есть все средства для его вычисления.


Конкретно у fstream — да.

Случается, что istream используется как интерфейс к custom streambuf'у и получит размер нет возможности...
Re[7]: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 27.08.03 14:56
Оценка: 7 (1)
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>Мне кажется странным выделять память с запасом при вполне "известном" размере файла. Во всяком случае, есть все средства для его вычисления.


ME>Конкретно у fstream — да.


ME>Случается, что istream используется как интерфейс к custom streambuf'у и получит размер нет возможности...


Но, попыться-то можно. См 27.6.1.3 п.

pos_type tellg();
basic_istream& seekg(pos_type pos);
basic_istream& seekg(off_type off, ios_base::seek_dir way);


Это методы istream, а не ifstream. А технику как это сделать я уже привел.
Re[5]: STL: банальный вопрос
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 27.08.03 15:12
Оценка:
Здравствуйте, MaximE, Вы писали:

OE>>    vector<char> filedata( ( istreambuf_iterator<char>( inputFile ) ),  istreambuf_iterator<char>() );


ME>На мой взгляд, пример этот слишком экстремален. Редко встречается, когда в пустой вектор с capacity() == 0 читают файл неизвестного размера.


ME>Лично я, когда читаю небольшой файл, то делаю reserve() с запасом. А большие файлы, когда важна производительность, лучше отображать.


я пробовал в этом примерчике делать сначала reserve() под размер файла, а потом

   filedata.assign( ( istreambuf_iterator<char>( inputFile ) ),  istreambuf_iterator<char>() );


или

   filedata.insert( filedata.begin(), ( istreambuf_iterator<char>( inputFile ) ),  istreambuf_iterator<char>() );


результаты совершенно одинаковые с интервальным конструктором.
Re[8]: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 27.08.03 15:13
Оценка:
В догон:

#include <iostream>


std::istream::pos_type probe(std::istream &stream)
{
    std::istream::pos_type oldpos = stream.tellg();
    std::istream::pos_type size = 0;

    if( stream.seekg(0, std::ios::end) )
       size = stream.tellg();

    stream.seekg(oldpos, std::ios::beg);

    return size;
}    
    

int main()
{
    std::cout << probe(std::cin);
    return 0;
}
Re[6]: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 27.08.03 15:40
Оценка: 3 (1)
OE>результаты совершенно одинаковые с интервальным конструктором.

Решающую роль в производительности интервального конструктора вектора играет тип итератора. В данном случае итератор не является итератором произвольного доступа. Отсюда и провал в производительности, а именно: при вычислении дистанции и переносе памяти.
Re[6]: STL: банальный вопрос
От: Анатолий Широков СССР  
Дата: 27.08.03 15:52
Оценка: 9 (1)
В данном случае, интерес представляет связка, приведенная Анонимом (reserve+copy). Вот она должна отработать поэффективней, чем вариант с интервальным конструктором, поскольку не происходит лишних телодвижений в отношении расчета дистанции:


std::vector<char> v;
v.reserve(1000000);
std::copy((istreambuf_iterator<char>( inputFile )),  istreambuf_iterator<char>(), std::back_inserter(v));



Подтверждается?
Re[8]: STL: банальный вопрос
От: MaximE Великобритания  
Дата: 27.08.03 17:42
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

ME>>Случается, что istream используется как интерфейс к custom streambuf'у и получит размер нет возможности...


АШ>Но, попыться-то можно. См 27.6.1.3 п.


АШ>
АШ>pos_type tellg();
АШ>basic_istream& seekg(pos_type pos);
АШ>basic_istream& seekg(off_type off, ios_base::seek_dir way);
АШ>


АШ>Это методы istream, а не ifstream. А технику как это сделать я уже привел.


Да, но у меня были буферы, которые не реализовывали seekxxx()
Re[4]: STL: банальный вопрос
От: artgonch  
Дата: 28.08.03 06:35
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>Хочу сравнить эффективность своего варианта с предложенным. Не сочтите за труд. Пусть входной файл будет в 1Mb.


OE>vc71, release, оптимизация по скорости.


OE>
OE>// file2vect.cpp : Defines the entry point for the console application.
OE>//

OE>#include "stdafx.h"
OE>#include <Windows.h>
OE>#include <vector>
OE>#include <iostream>
OE>#include <fstream>

OE>using namespace std;

OE>int _tmain( int argc, _TCHAR* argv[] )
OE>{
OE>    DWORD t1 = GetTickCount();

OE>    ifstream inputFile( "E:\\PROJECTS\\VC71\\tests\\file2vect\\filename.txt", ios::in | ios::binary );

OE>    if( !inputFile )
OE>    {
OE>        cout << "file open error!!!" << endl;
OE>        return 1;
OE>    }

OE>    vector<char> filedata( ( istreambuf_iterator<char>( inputFile ) ),  istreambuf_iterator<char>() );

OE>    DWORD t2 = GetTickCount();

OE>    cout<< "vector size = " << filedata.size() << ", loading time  = " << t2 - t1 << " ms." << endl;

OE>    return 0;
OE>}
OE>


OE>вывод, несколько запусков:


OE>
OE>vector size = 2027953, loading time  = 211 ms.
OE>vector size = 2027953, loading time  = 210 ms.
OE>vector size = 2027953, loading time  = 210 ms.
OE>vector size = 2027953, loading time  = 211 ms.
OE>


OE>второй вариант:


OE>
OE>// file2vect2.cpp : Defines the entry point for the console application.
OE>//

OE>#include "stdafx.h"
OE>#include <windows.h>
OE>#include <iostream>
OE>#include <fstream>
OE>#include <vector>
OE>#include <time.h>

OE>using namespace std;

OE>int main()
OE>{
OE>    DWORD t1 = GetTickCount();

OE>    std::ifstream f("E:\\PROJECTS\\VC71\\tests\\file2vect\\filename.txt", std::ios::in | std::ios::binary);

OE>    if( !f )
OE>    {
OE>        cout << "file open error!!!" << endl;
OE>        return 1;
OE>    }

OE>    std::vector<char> buffer;
OE>    std::ifstream::pos_type size = 0;

OE>    if( f.seekg(0, std::ios::end) )
OE>    {
OE>       size = f.tellg();
OE>    }

OE>    if( size && f.seekg(0, std::ios::beg) )
OE>    {
OE>       buffer.resize(size);
OE>       f.read(&buffer[0], size);
OE>    }
    
OE>    DWORD t2 = GetTickCount();

OE>    cout<< "vector size = " << buffer.size() << ", loading time  = " << t2 - t1 << " ms." << endl;

OE>    return 0;
OE>}
OE>


OE>вывод, несколько запусков:


OE>
OE>vector size = 2027953, loading time  = 20 ms.
OE>vector size = 2027953, loading time  = 10 ms.
OE>vector size = 2027953, loading time  = 20 ms.
OE>vector size = 2027953, loading time  = 10 ms.
OE>


OE>с чем вас и поздравляю


OE>на больших файлах различия несколько сглаживаются:


OE>
OE>E:\PROJECTS\VC71\tests\file2vect\file2vect\Release\file2vect.exe
OE>vector size = 322525944, loading time  = 88187 ms.

OE>E:\PROJECTS\VC71\tests\file2vect\file2vect2\Release\file2vect2.exe
OE>vector size = 322525944, loading time  = 37514 ms.
OE>
Re: Как наилучшим образом считать файл в буффер?
От: Andrew S Россия http://alchemy-lab.com
Дата: 28.10.04 09:27
Оценка:
Надо убрать одну 'ф' из буфера, а то в Q&A отображается неправильно...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Как наилучшим образом считать файл в буфер?
От: xmen  
Дата: 19.07.08 20:49
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>второй вариант:


OE>
OE>// file2vect2.cpp : Defines the entry point for the console application.
OE>//

OE>#include "stdafx.h"
OE>#include <windows.h>
OE>#include <iostream>
OE>#include <fstream>
OE>#include <vector>
OE>#include <time.h>

OE>using namespace std;

OE>int main()
OE>{
OE>    DWORD t1 = GetTickCount();

OE>    std::ifstream f("E:\\PROJECTS\\VC71\\tests\\file2vect\\filename.txt", std::ios::in | std::ios::binary);

OE>    if( !f )
OE>    {
OE>        cout << "file open error!!!" << endl;
OE>        return 1;
OE>    }

OE>    std::vector<char> buffer;
OE>    std::ifstream::pos_type size = 0;

OE>    if( f.seekg(0, std::ios::end) )
OE>    {
OE>       size = f.tellg();
OE>    }

OE>    if( size && f.seekg(0, std::ios::beg) )
OE>    {
OE>       buffer.resize(size);
OE>       f.read(&buffer[0], size);
OE>    }
    
OE>    DWORD t2 = GetTickCount();

OE>    cout<< "vector size = " << buffer.size() << ", loading time  = " << t2 - t1 << " ms." << endl;

OE>    return 0;
OE>}
OE>


OE>вывод, несколько запусков:


OE>
OE>vector size = 2027953, loading time  = 20 ms.
OE>vector size = 2027953, loading time  = 10 ms.
OE>vector size = 2027953, loading time  = 20 ms.
OE>vector size = 2027953, loading time  = 10 ms.
OE>


OE>с чем вас и поздравляю


OE>на больших файлах различия несколько сглаживаются:


OE>
OE>E:\PROJECTS\VC71\tests\file2vect\file2vect\Release\file2vect.exe
OE>vector size = 322525944, loading time  = 88187 ms.

OE>E:\PROJECTS\VC71\tests\file2vect\file2vect2\Release\file2vect2.exe
OE>vector size = 322525944, loading time  = 37514 ms.
OE>


#define UNICODE
#include <stdio.h>
#include <windows.h>

main()
{
    DWORD t1 = GetTickCount();
    
    HANDLE hFile = CreateFile(TEXT("file.bin"), 
                              GENERIC_READ,
                              0,
                              NULL,
                              OPEN_EXISTING,
                              0,
                              0);
    
    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("Error: CreateFile = INVALID_HANDLE_VALUE\n");
        return;
    }
    
    LPVOID buf = 0;
    DWORD size = 0;
    DWORD dw;
    
    size = GetFileSize(hFile, NULL);
    
    buf = HeapAlloc(GetProcessHeap(), 0, size);
    
    if (!buf)
    {
        printf("Error: HeapAlloc = %d\n", GetLastError());
        return;
    }
    
    if (!ReadFile(hFile, buf, size, &dw, NULL))
    {
        printf("Error: ReadFile = %d\n", GetLastError());
        return;
    }
    
    DWORD t2 = GetTickCount();

    printf("vector size = %d, loading time = %d ms.\n", size, t2 - t1);
    
    HeapFree(GetProcessHeap(),0, buf);
    CloseHandle(hFile);
}


S:\!IVAN\cpp>2.exe
--------------------------------------------------
S:\cpp>file2vect2.exe
vector size = 13107200, loading time  = 94 ms.

S:\cpp>FileToBuf.exe
vector size = 14308877, loading time = 31 ms.
--------------------------------------------------
S:\cpp>file2vect2.exe
vector size = 734255104, loading time  = 16469 ms.

S:\cpp>FileToBuf.exe
vector size = 734410752, loading time = 11282 ms.
--------------------------------------------------
S:\cpp>file2vect2.exe
vector size = 734332928, loading time  = 18297 ms.

S:\cpp>FileToBuf.exe
vector size = 733882368, loading time = 11453 ms.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.