Как прочитать содержимое файла в istringstream?
Чтобы улучшить производительность чтения из файла, я пытаюсь прочитать весь контент большого (несколько МБ) файла в память и затем использовать поток istringstream для доступа к информации.
У меня вопрос, как лучше всего прочитать эту информацию и "импортировать" ее в поток строк? Проблема этого подхода (см. Ниже) заключается в том, что при создании потока строк буферы копируются, а использование памяти удваивается.
#include <fstream>
#include <sstream>
using namespace std;
int main() {
ifstream is;
is.open (sFilename.c_str(), ios::binary );
// get length of file:
is.seekg (0, std::ios::end);
long length = is.tellg();
is.seekg (0, std::ios::beg);
// allocate memory:
char *buffer = new char [length];
// read data as a block:
is.read (buffer,length);
// create string stream of memory contents
// NOTE: this ends up copying the buffer!!!
istringstream iss( string( buffer ) );
// delete temporary buffer
delete [] buffer;
// close filestream
is.close();
/* ==================================
* Use iss to access data
*/
}
4 ответа
std::ifstream
есть метод rdbuf()
, который возвращает указатель на filebuf
, Затем вы можете "нажать" это filebuf
в ваш stringstream
:
int main()
{
std::ifstream file( "myFile" );
if ( file )
{
std::stringstream buffer;
buffer << file.rdbuf();
file.close();
// operations on the buffer...
}
}
РЕДАКТИРОВАТЬ: Как отмечает Мартин Йорк в комментариях, это может быть не самым быстрым решением, так как stringstream
"s operator<<
будет читать файл буфера символ за символом. Вы можете проверить его ответ, где он использует ifstream
"s read
метод, как вы привыкли делать, а затем установите stringstream
буфер для указания на ранее выделенную память.
ХОРОШО. Я не говорю, что это будет быстрее, чем чтение из файла
Но это метод, в котором вы создаете буфер один раз, а после того, как данные считываются в буфер, используйте его непосредственно в качестве источника для потока строк.
NB Стоит отметить, что std::ifstream буферизован. Он читает данные из файла в виде (относительно больших) кусков. Потоковые операции выполняются с буфером, возвращающимся в файл только для следующего чтения, когда требуется больше данных. Поэтому, прежде чем засосать все данные в память, убедитесь, что это горлышко бутылки.
#include <fstream>
#include <sstream>
#include <vector>
int main()
{
std::ifstream file("Plop");
if (file)
{
/*
* Get the size of the file
*/
file.seekg(0,std::ios::end);
std::streampos length = file.tellg();
file.seekg(0,std::ios::beg);
/*
* Use a vector as the buffer.
* It is exception safe and will be tidied up correctly.
* This constructor creates a buffer of the correct length.
*
* Then read the whole file into the buffer.
*/
std::vector<char> buffer(length);
file.read(&buffer[0],length);
/*
* Create your string stream.
* Get the stringbuffer from the stream and set the vector as it source.
*/
std::stringstream localStream;
localStream.rdbuf()->pubsetbuf(&buffer[0],length);
/*
* Note the buffer is NOT copied, if it goes out of scope
* the stream will be reading from released memory.
*/
}
}
Это кажется преждевременной оптимизацией для меня. Сколько работы делается в обработке. Предполагая современный настольный компьютер / сервер, а не встроенную систему, копирование нескольких МБ данных во время инициализации довольно дешево, особенно по сравнению с чтением файла с диска в первую очередь. Я хотел бы придерживаться того, что у вас есть, измерить систему, когда она будет завершена, и решить, будет ли потенциальное повышение производительности того стоить. Конечно, если память ограничена, это происходит во внутреннем цикле или в программе, которая часто вызывается (например, раз в секунду), которая меняет баланс.
Следует также помнить, что файловый ввод / вывод всегда будет самой медленной операцией. Решение Люка Турэля верное, но есть и другие варианты. Чтение всего файла в память за раз будет намного быстрее, чем отдельное чтение.