Как прочитать весь поток в std::string?
Я пытаюсь прочитать весь поток (несколько строк) в строку.
Я использую этот код, и он работает, но это оскорбляет мое чувство стиля... Конечно, есть более простой способ? Может быть, с использованием струнных потоков?
void Obj::loadFromStream(std::istream & stream)
{
std::string s;
std::streampos p = stream.tellg(); // remember where we are
stream.seekg(0, std::ios_base::end); // go to the end
std::streamoff sz = stream.tellg() - p; // work out the size
stream.seekg(p); // restore the position
s.resize(sz); // resize the string
stream.read(&s[0], sz); // and finally, read in the data.
На самом деле,
const
ссылка на строку тоже подойдет, и это может упростить задачу...const std::string &s(... a miracle occurs here...)
6 ответов
Как насчет
std::istreambuf_iterator<char> eos;
std::string s(std::istreambuf_iterator<char>(stream), eos);
(может быть однострочным, если не для MVP)
редактирование после 2011 года, этот подход теперь записан
std::string s(std::istreambuf_iterator<char>(stream), {});
Я опаздываю на вечеринку, но вот довольно эффективное решение:
std::string gulp(std::istream &in)
{
std::string ret;
char buffer[4096];
while (in.read(buffer, sizeof(buffer)))
ret.append(buffer, sizeof(buffer));
ret.append(buffer, in.gcount());
return ret;
}
Я провел некоторый бенчмаркинг, и оказалось, что std::istreambuf_iterator
Техника ( используется принятым ответом) на самом деле намного медленнее. На gcc 4.4.5 с -O3
на моей машине разница примерно в 4,5 раза, и разрыв становится больше с более низкими настройками оптимизации.
Вы могли бы сделать
std::string s;
std::ostringstream os;
os<<stream.rdbuf();
s=os.str();
но я не знаю, эффективнее ли это.
Альтернативная версия:
std::string s;
std::ostringstream os;
stream>>os.rdbuf();
s=os.str();
Вы можете попробовать использовать что-то из алгоритмов. Я должен быть готов к работе, но вот очень быстрый удар по делу (должен быть лучший способ):
copy( istreambuf_iterator<char>(stream), istreambuf_iterator<char>(), back_inserter(s) );
Хорошо, если вы ищете простой и "читаемый" способ сделать это. Я бы рекомендовал добавить / использовать некоторые высокоуровневые фреймворки в вашем проекте. Для этого я всегда использую Poco и Boost во всех своих проектах. В этом случае с Poco:
string text;
FileStream fstream(TEXT_FILE_PATH);
StreamCopier::copyToString(fstream, text);
Как насчет использования getline с разделителем? Следующий код помогает мне прочитать весь std::cin в строке в ubuntu с g++-10.
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
getline(cin, s, {}); //the whole stream into variable s
return 0;
}
Возможно, это одно строчное C++11 решение:
std::vector<char> s{std::istreambuf_iterator<char>{in},{}};