使用迭代器将部分文件流读入字符串

Ali*_*_SM 6 c++ string iterator

这是我到目前为止所尝试的但没有成功:

std::string ReadPartial( std::ifstream& _file, int _size )
{
    std::istreambuf_iterator<char> first( _file );
    std::istreambuf_iterator<char> last( _file );
    std::advance( last, _size );
    return std::string( first, last ); 
}
Run Code Online (Sandbox Code Playgroud)

我知道如何阅读整个文件.

std::string Read( std::ifstream& _file )
{
    std::istreambuf_iterator<char> first( _file );
    std::istreambuf_iterator<char> last();
    return std::string( first, last ); 
}
Run Code Online (Sandbox Code Playgroud)

但这不是我想要做的.我收到一个空字符串.如果我在调试器中查看第一个也是最后一个,即使在std :: advance之后它们指向同一个东西.

Mar*_*tos 5

你想使用迭代器有什么特别的原因吗?你可以一次读取字节:

std::string s(_size, '\0');
_file.read(&s[0], _size);
Run Code Online (Sandbox Code Playgroud)

如果你真的想用迭代器读取,你可以这样做:

std::string ReadPartial( std::ifstream& _file, int _size )
{
    std::istreambuf_iterator<char> first( _file );
    std::istreambuf_iterator<char> last;
    std::string s;
    s.reserve(_size);
    while (_size-- && first != last) s += *first++;
    return s;
}
Run Code Online (Sandbox Code Playgroud)

  • `file.read(&s [0],size)`是不可移植且不安全的.basic_string没有vector的连续存储保证. (2认同)
  • @Steve:连续存储是[通过索引编制字符串所必需的](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530)(缺少的是明确的保证迭代器).0x为std :: string保证所有方式的连续存储. (2认同)

小智 5

std::istreambuf_iterator<char> first( _file );
std::istreambuf_iterator<char> last( _file );
std::advance( last, _size );
Run Code Online (Sandbox Code Playgroud)

istreambuf_iterators是输入迭代器.一旦前进,另一个迭代器也会被修改. 您将它们视为Forward Iterators,它具有可以复制迭代器,推进它,然后通过推进副本获得相同序列的属性.

对于一般情况:

template<class InIter, class Size, class OutIter>
void copy_n(InIter begin, InIter end, Size n, OutIter dest) {
  for (; begin != end && n > 0; ++begin, --n) {
    *dest++ = *begin;
  }
}

//...
std::string ReadPartial(std::istream& file, int size) {
  std::string result;
  copy_n(istreambuf_iterator<char>(file), istreambuf_iterator<char>(),
         size, back_inserter(result));
  return result;
}
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,最好使用istream :: read直接调整字符串的大小,然后检查您是否读取了所需的字符数.