Эффективный способ чтения файла в 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()
.
Этот вопрос связан не столько с тем, насколько важны эти накладные расходы. Скорее, мне просто интересно узнать, есть ли другой способ.
Ответы
Ответ 1
Каноническая форма такова:
#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>());
Ответ 2
Если вам требуется истинное чтение нулевой копии, то есть для исключения копирования из ядра в пространство пользователя, просто скопируйте файл в память. Напишите свою собственную сопоставленную оболочку файла или используйте ее из boost::interprocess
.
Ответ 3
Если я правильно вас понимаю, вы хотите прочитать каждый элемент, но не хотите загружать его все в fileContents
, правильно?
Я лично не думаю, что это сделало бы ненужные копии, потому что открытые файлы несколько раз снижали бы производительность. В этом случае однократное чтение вектора fileContents
является разумным решением.