将固定长度的数据从std :: istream复制到字符串

时间:2014-11-21 12:32:51

标签: c++ iostream

我想将std :: istream中固定长度的数据复制到字符串中:

std::istream & operator >> ( std::istream & is, LogMsg & msg )
{
    // read in 4 bytes - a uint32_t that describes the number of bytes in message:
    // next, read the message bytes into the LogMsg

    typedef std::istream_iterator<unsigned char> Iter;

    Iter            i (is);
    uint32_t        nSize   = 0;
    std::string &   sMsg    = msg.MsgRef();

    is >> nSize;
    sMsg.reserve(nSize);

    std::copy(
        i.begin(), i.begin() + nSize,
        std::back_inserter(sMsg)
    );

    return is;
}

我不能使用这个解决方案,因为迭代器上的std :: istream_iterator :: begin()函数只是c ++ 11(我被约束为-std = gnu ++ 0x with gcc 4.4.7

那么,如何将输入流中固定长度的数据复制到字符串中呢?

我最初喜欢std :: istream :: read,这似乎很合适 - 它有以下语法

is.read (buffer,length);

但我不认为你可以读入字符串的内部缓冲区,我想避免复制到临时缓冲区。我可以用某种方式使用streambuf吗?

3 个答案:

答案 0 :(得分:3)

您可以复制到字符串的内部缓冲区,只需确保它的大小合适:

sMsg.resize(nSize);
is.read(&sMsg[0], nSize);

它的效率低于使用begin()的解决方案,因为您必须对要立即覆盖的大量数据进行零初始化。但它将在C ++之前的11版本中运行。

答案 1 :(得分:3)

使用std::copy_n()

std::copy_n(i, nSize, std::back_inserter(sMsg));

答案 2 :(得分:3)

明显的解决方案是std::copy_n

std::copy_n( std::istreambuf_iterator<char>( is ), size, std::back_inserter( msg ) );

这只有在你可以确定字符在那里时才有效, 然而。如果您在尝试阅读时遇到文件结尾 字符,未定义的行为随之而来。这意味着尽管如此 一个明显的解决方案,它可能不是一个好的解决方案。

然而,在C ++ 11中,正式地,在早期的实现中,在 练习,你可以读入内部缓冲区。你必须确定 该字符串有足够的空间:

msg.resize( size );
is.read( &msg[0], msg.size() );

(由于某种原因,没有非const版本的 std::string::data(),尽管保证了潜在的连续性 C ++ 11)