web-dev-qa-db-ja.com

ファイルをstd :: vector <char>に読み込む効率的な方法?

不要なコピーを避けたい。私は次の線に沿って何かを目指しています:

_std::ifstream testFile( "testfile", "rb" );
std::vector<char> fileContents;
int fileSize = getFileSize( testFile );
fileContents.reserve( fileSize );
testFile.read( &fileContents[0], fileSize );
_

reserveは実際にはベクターに何も挿入しないので機能しません。したがって、_[0]_にアクセスできません)。

もちろん、std::vector<char> fileContents(fileSize)は機能しますが、すべての要素を初期化するオーバーヘッドがあります(fileSizeはかなり大きくなる可能性があります)。 resize()についても同様です。

この質問は、オーバーヘッドがどれほど重要であるかについてはそれほど重要ではありません。むしろ、別の方法があるかどうか知りたいだけです。

36
Pedro d'Aquino

正規形は次のとおりです。

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)),
                               std::istreambuf_iterator<char>());

再割り当てが心配な場合は、ベクター内のスペースを予約してください。

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents;
fileContents.reserve(fileSize);
fileContents.assign(std::istreambuf_iterator<char>(testFile),
                    std::istreambuf_iterator<char>());
60
wilhelmtell

真のゼロコピー読み取りが必要な場合、つまり、カーネルからユーザー空間へのコピーを排除するには、ファイルをメモリにマッピングします。独自のマップされたファイルラッパーを記述するか、boost::interprocessのラッパーを使用します。

4

私があなたを正しく理解しているなら、あなたは各要素を読みたいのですが、すべてをfileContentsにロードしたくないのですよね?ファイルを複数回開くとパフォーマンスがさらに低下するため、個人的にこれが不要なコピーを作成するとは思わない。この場合、fileContentsvectorへの1回の読み取りは合理的な解決策です。

0
Chan