파일 콘텐츠를 istringstream으로 읽는 방법은 무엇입니까?
-
02-07-2019 - |
문제
파일에서 성능 읽기를 향상시키기 위해 큰 (여러 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의 솔루션은 정확하지만 다른 옵션이 있습니다. 전체 파일을 한 번에 메모리에 읽는 것은 별도의 읽기보다 훨씬 빠릅니다.