繁体   English   中英

直接从std :: istream读取到std :: string

[英]Reading directly from an std::istream into an 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;

std::string有一个你可以使用的resize函数,或者是一个会做同样的构造函数:

boost::uint16_t len;
is.read((char*)&len, 2);

std::string str(len, '\0');
is.read(&str[0], len);

这是未经测试的,我不知道是否要求字符串具有连续存储。

您可以使用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;
}

没有复制,没有黑客,没有超支的可能性,没有未定义的行为。

你可以使用像getline这样的东西:

#include <iostream>
#include <string>
using namespace std;

int main () {
  string str;
  getline (cin,str,' ');
}

我会使用矢量作为缓冲区。

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所述)。 字符串成员处于连续位置的标准不能保证(因此请检查当前的实现并在移植到另一个编译器/平台时进行需要检查的大注释)。

一个简单的方法是:

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);

你只是优化代码长度或试图在这里保存自己的副本? 临时缓冲区出了什么问题?

我认为你实际上正在规避字符串的保护,试图直接写这样做。 如果您担心复制到std :: string的性能,因为您已经发现它在某种程度上影响了应用程序的性能,我会直接使用char *。

编辑:做更多的看... 从char *初始化std :: string没有副本

在第二个答案中,它说得非常平坦,你无法实现你想要实现的目标(即填充std :: string而不需要迭代char *来复制。)

看看你的加载例程(可能在这里发布它?)并最小化分配:new和delete当然不是免费的,所以如果你不必经常重新创建缓冲区,你至少可以节省一些时间。 我总是发现它有助于通过memset将缓冲区擦除为0或者每次迭代终止数组的第一个索引,但是一旦你对算法有信心,你就可以迅速消除代码的性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM