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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1816319/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:14:36  来源:igfitidea点击:

Reading directly from an std::istream into an std::string

c++stdstringiostream

提问by Fire Lancer

Is there anyway to read a known number of bytes, directly into an std::string, without creating a temporary buffer to do so?

无论如何,是否可以将已知数量的字节直接读取到 std::string 中,而无需为此创建临时缓冲区?

eg currently I can do it by

例如目前我可以通过

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;

采纳答案by GManNickG

std::stringhas a resizefunction you could use, or a constructor that'll do the same:

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

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

std::string str(len, '
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;
}
'); is.read(&str[0], len);

This is untested, and I don't know if strings are mandated to have contiguous storage.

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

回答by dex black

You could use a combination of copy_n and an insert_iterator

您可以使用 copy_n 和 insert_iterator 的组合

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

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

no copying, no hacks, no possibility of overrun, no undefined behaviour.

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

回答by rmn

You could use something like getline:

你可以使用类似 getline 的东西:

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

回答by Martin York

I would use a vector as the buffer.

我会使用一个向量作为缓冲区。

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

Though you will probably get away with using a string as the buffer (as described by GMan). It is not guaranteed by the standard that a strings members are in consecutive locations (so check your current implementation and put a big comment that it needs checking when porting to another compiler/platform).

尽管您可能会使用字符串作为缓冲区(如 GMan 所述)。标准不能保证字符串成员位于连续位置(因此请检查您当前的实现并在移植到另一个编译器/平台时添加需要检查的大注释)。

回答by antik

Are you just optimizing code length or trying to save yourself a copy here? What's wrong with the temporary buffer?

您是在优化代码长度还是试图在此处为自己保存一份副本?临时缓冲区有什么问题?

I'd argue that you're actually circumventing the protections of the string trying to write directly do it like that. If you're worried about performance of the copy to a std::string because you've identified that it's in some way affecting the performance of your application, I'd work directly with the char*.

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

EDIT: Doing more looking... initializing std::string from char* without copy

编辑:做更多的事情...... 从 char* 初始化 std::string 而无需复制

In the second answer, it's stated pretty flatly that you can't achieve what you're looking to achieve (ie. populate a std::string without an iteration over the char* to copy.)

在第二个答案中,它非常断然地说您无法实现您想要实现的目标(即填充 std::string 而无需对 char* 进行迭代复制。)

Take a look at your load routine (post it here perhaps?) and minimize allocations: new and delete certainly aren't free so you can at least save some time if you don't have to re-create the buffer constantly. I always find it helpful erase it by memset'ing the buffer to 0 or null terminating the first index of the array each iteration but you may quickly eliminate that code in the interests of performance once you're confident in your algorithm.

看看你的加载例程(也许可以在这里发布?)并最小化分配:new 和 delete 肯定不是免费的,所以如果你不必经常重新创建缓冲区,你至少可以节省一些时间。我总是发现通过将缓冲区内存设置为 0 或 null 来终止数组的第一个索引每次迭代都会有帮助,但是一旦您对算法有信心,您可以快速删除该代码以提高性能。

回答by Marmara

An easy way would be:

一个简单的方法是:

##代码##