Загрузка файла в вектор <char>
Я хотел бы загрузить содержимое текстового файла в vector<char>
(или в любой итератор ввода char, если это возможно). В настоящее время мой код выглядит следующим образом:
std::vector<char> vec;
std::ifstream file("test.txt");
assert(file.is_open());
while (!(file.eof() || file.fail())) {
char buffer[100];
file.read(buffer, 100);
vec.insert(vec.end(), buffer, buffer + file.gcount());
}
Мне не нравится ручное использование буфера (почему 100 символов? Почему не 200, или 25 или что-то еще?) или большое количество строк, которые это взяли. Код просто кажется очень уродливым и не-С++. Есть ли более прямой способ сделать это?
Ответы
Ответ 1
Если вы хотите не читать char с помощью char:
if (!file.eof() && !file.fail())
{
file.seekg(0, std::ios_base::end);
std::streampos fileSize = file.tellg();
vec.resize(fileSize);
file.seekg(0, std::ios_base::beg);
file.read(&vec[0], fileSize);
}
Ответ 2
Я думаю, что-то вроде этого, но не имеет среды для его проверки:
std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(vec));
Возможно, вам нужно играть с io-манипуляторами для таких вещей, как linebreaks/whitespace.
Изменить: как отмечено в комментариях, может быть удар по производительности.
Ответ 3
используйте итератор:
#include <iterator>
istream_iterator<char> data( file );
istream_iterator<char> end;
vec.insert( std::back_inserter(vec), data, end );
Ответ 4
Другой подход, используя rdbuf()
, сначала прочитать весь файл std::stringstream
:
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
// for check:
#include <algorithm>
#include <iterator>
#include <iostream>
int main() {
std::ifstream file("test.cc");
std::ostringstream ss;
ss << file.rdbuf();
const std::string& s = ss.str();
std::vector<char> vec(s.begin(), s.end());
// check:
std::copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout));
}
Ответ 5
Было много хороших ответов. Спасибо всем! Код, который я решил использовать, следующий:
std::vector<char> vec;
std::ifstream file;
file.exceptions(
std::ifstream::badbit
| std::ifstream::failbit
| std::ifstream::eofbit);
//Need to use binary mode; otherwise CRLF line endings count as 2 for
//`length` calculation but only 1 for `file.read` (on some platforms),
//and we get undefined behaviour when trying to read `length` characters.
file.open("test.txt", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
std::streampos length(file.tellg());
if (length) {
file.seekg(0, std::ios::beg);
vec.resize(static_cast<std::size_t>(length));
file.read(&vec.front(), static_cast<std::size_t>(length));
}
Очевидно, что это не подходит для чрезвычайно больших файлов или критичных по производительности кода, но это достаточно хорошо для общего использования.