Вопрос

Чтобы повысить производительность чтения из файла, я пытаюсь прочитать все содержимое большого файла (несколько МБ) в памяти, а затем использовать поток 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
   */

}
Это было полезно?

Решение

std::ifstream есть метод rdbuf(), который возвращает указатель на filebuf.Затем вы можете «надавить» на это filebuf в твой stringstream:

#include <fstream>
#include <sstream>

int main()
{
    std::ifstream file( "myFile" );

    if ( file )
    {
        std::stringstream buffer;

        buffer << file.rdbuf();

        file.close();

        // operations on the buffer...
    }
}

РЕДАКТИРОВАТЬ:Как отмечает Мартин Йорк в комментариях, возможно, это не самое быстрое решение, поскольку stringstream's operator<< будет читать filebuf посимвольно.Возможно, вы захотите проверить его ответ, где он использует ifstream's read метод, как вы это делали раньше, а затем установите stringstream буфер, указывающий на ранее выделенную память.

Другие советы

ХОРОШО.Я не говорю, что это будет быстрее, чем чтение из файла.

Но это метод, при котором вы создаете буфер один раз, а после того, как данные считываются в буфер, используете его непосредственно в качестве источника для строкового потока.

Н.Б.Стоит отметить, что 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.
         */
    }
}

Мне это кажется преждевременной оптимизацией.Какой объем работы выполняется при обработке.Если предположить, что это современный настольный компьютер/сервер, а не встроенная система, копирование нескольких МБ данных во время инициализации обходится довольно дешево, особенно по сравнению с первым чтением файла с диска.Я бы остановился на том, что у вас есть, измерил бы систему, когда она будет завершена, и решил бы, стоит ли того потенциальное увеличение производительности.Конечно, если памяти мало, это происходит во внутреннем цикле или в программе, которая вызывается часто (например, раз в секунду), что меняет баланс.

Еще следует иметь в виду, что файловый ввод-вывод всегда будет самой медленной операцией.Решение Люка Турая правильное, но есть и другие варианты.Чтение всего файла в память одновременно будет намного быстрее, чем чтение по отдельности.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top