문제

파일에서 성능 읽기를 향상시키기 위해 큰 (여러 MB) 파일의 전체 내용을 메모리에 읽은 다음 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...
    }
}

편집 : Martin York이 의견에서 언급 한 것처럼 이것은 다음과 같은 이후로 가장 빠른 해결책이 아닐 수도 있습니다. stringstream'에스 operator<< 문자별로 filebuf 문자를 읽습니다. 그가 사용하는 곳에서 그의 대답을 확인하고 싶을 수도 있습니다. ifstream'에스 read 예전처럼 방법을 설정 한 다음 stringstream 이전에 할당 된 메모리를 가리키는 버퍼.

다른 팁

확인. 나는 이것이 파일에서 읽는 것보다 더 빨라질 것이라고 말하는 것이 아닙니다.

그러나 이것은 버퍼를 한 번 그리고 데이터를 버퍼로 읽은 후에 버퍼를 작성하는 방법입니다.

NBstd :: 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.
         */
    }
}

이것은 나에게 조기 최적화처럼 보입니다. 처리에서 얼마나 많은 작업이 이루어지고 있습니다. 임베디드 시스템이 아닌 현대적인 데스크탑/서버를 가정하면, 특히 디스크 파일을 읽는 것과 비교할 때, 심각한 시스템을 복사하는 것은 상당히 저렴합니다. 나는 당신이 가진 것을 고수하고, 시스템이 완료되었을 때 시스템을 측정하고, 잠재적 성능 이익이 그만한 가치가 있는지 결정할 것입니다. 물론 메모리가 빡빡하면 이것은 내부 루프 또는 종종 (초 1 년과 같이) 호출되는 프로그램으로 균형을 변경합니다.

명심해야 할 또 다른 것은 파일 I/O가 항상 가장 느린 작업이 될 것입니다. Luc Touraille의 솔루션은 정확하지만 다른 옵션이 있습니다. 전체 파일을 한 번에 메모리에 읽는 것은 별도의 읽기보다 훨씬 빠릅니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top