Чтение непосредственно из std:: istream в std::string
В любом случае, чтобы прочитать известное количество байтов, непосредственно в std::string, без создания временного буфера для этого?
Например, в настоящее время я могу сделать это с помощью
boost::uint16_t len;
is.read((char*)&len, 2);
char *tmpStr = new char[len];
is.read(tmpStr, len);
std::string str(tmpStr, len);
delete[] tmpStr;
Ответы
Ответ 1
std::string
имеет функцию resize
, которую вы могли бы использовать, или конструктор, который будет делать то же самое:
boost::uint16_t len;
is.read((char*)&len, 2);
std::string str(len, '\0');
is.read(&str[0], len);
Это не проверено, и я не знаю, должны ли строки иметь непрерывное хранилище.
Ответ 2
Вы можете использовать комбинацию copy_n и insert_iterator
void test_1816319()
{
static char const* fname = "test_1816319.bin";
std::ofstream ofs(fname, std::ios::binary);
ofs.write("\x2\x0", 2);
ofs.write("ab", 2);
ofs.close();
std::ifstream ifs(fname, std::ios::binary);
std::string s;
size_t n = 0;
ifs.read((char*)&n, 2);
std::istream_iterator<char> isi(ifs), isiend;
std::copy_n(isi, n, std::insert_iterator<std::string>(s, s.begin()));
ifs.close();
_unlink(fname);
std::cout << s << std::endl;
}
нет копирования, нет хаков, нет возможности перерасхода, нет undefined.
Ответ 3
Вы можете использовать что-то вроде getline:
#include <iostream>
#include <string>
using namespace std;
int main () {
string str;
getline (cin,str,' ');
}
Ответ 4
Я бы использовал вектор в качестве буфера.
boost::uint16_t len;
is.read((char*)&len, 2); // Note if this file was saved from a different architecture
// then endianness of these two bytes may be reversed.
std::vector buffer(len); // uninitialized.
is.read(&buffer[0], len);
std::string str(buffer.begin(),buffer.end());
Хотя вам, вероятно, удастся использовать строку в качестве буфера (как описано в GMan). Стандарт не гарантирует, что члены строк находятся в последовательных местах (так что проверьте текущую реализацию и поставьте большой комментарий, который необходимо проверить при переносе на другой компилятор/платформу).
Ответ 5
Вы просто оптимизируете длину кода или пытаетесь сохранить здесь копию? Что случилось с временным буфером?
Я бы сказал, что вы на самом деле обходите защиту строкой, пытающейся написать прямо так, как это. Если вы беспокоитесь о производительности копии на std::string, потому что вы определили, что это каким-то образом влияет на производительность вашего приложения, я буду работать непосредственно с char *.
EDIT: делать больше...
инициализация std::string из char * без копирования
Во втором ответе он довольно четко заявил, что вы не можете достичь того, чего хотите достичь (т.е. заполнить std::string без повторения итерации по char *).
Взгляните на свою рутину загрузки (разместите ее здесь, возможно?) и минимизируйте выделение: новые и удалить, конечно, не являются бесплатными, поэтому вы можете хотя бы сэкономить некоторое время, если вам не нужно постоянно воссоздавать буфер, Я всегда нахожу, что это полезно, стереть его с помощью memset'ing буфера до 0 или нулевого завершения первого индекса массива на каждой итерации, но вы можете быстро устранить этот код в интересах производительности, как только вы уверены в своем алгоритме.
Ответ 6
Простым способом может быть:
std::istream& data
const size_t dataSize(static_cast<size_t>(data.rdbuf()->in_avail()));
std::string content;
content.reserve( dataSize);
data.read(&content[0], dataSize);