这个one stream命令如何在c ++的整个文件中读取?

时间:2018-03-29 01:16:53

标签: c++ ifstream stringstream streambuf

鉴于此:

auto f = std::ifstream{file};
if (f) {
    std::stringstream stream;
    stream << f.rdbuf();
    return stream.str();
}
return std::string{};

我不明白为什么会这样。 我不知道f是什么类型,因为它说auto,但显然你可以检查它是非零的。 但是当文件很大时,比如2 gig,运行的延迟发生在 这一行:

    stream << f.rdbuf();

文档说rdbuf()获取指向ifstream内部缓冲区的指针。因此,为了使其读取整个文件,缓冲区必须调整文件大小,并一次性加载所有文件。但是当流&lt;&lt;发生了,rdbuf()必须已经设置,否则它将无法返回一个点。 我希望构造函数在这种情况下可以做到这一点,但它显然是延迟加载的,因为在构造中读取整个文件对于其他所有用例都是坏的,并且延迟在流中&lt;&lt;命令。

有什么想法?所有其他堆栈溢出引用将文件读入字符串总是以某种方式循环。

如果涉及一些缓冲区,显然有,它有多大?如果它是1个字节,它肯定会很慢。

可爱的c ++非常不透明,对于那些必须知道幕后发生了什么的程序员来说是不好的。

3 个答案:

答案 0 :(得分:3)

当参数为operator<<时,它是ostreamstreambuf定义的函数。只要streambuf不是空指针,它就会从streambuf控制的输入序列中提取字符并将它们插入*this,直到满足以下条件之一(请参阅operator<< overload note #9):

  
      
  • 文件结尾出现在输入序列上;
  •   
  • 在输出序列中插入失败(在这种情况下,不会提取要插入的字符);
  •   
  • 发生异常(在这种情况下捕获异常)。
  •   

基本上,ostreamstringstream继承自)知道如何使用streambuf从与其关联的文件中提取所有数据。这是一个惯用的,但正如你所说,不是直观的,可以扼杀整个文件。 streambuf实际上并没有在这里缓冲所有数据(正如你所注意的,在一般情况下将整个文件读入缓冲区会很糟糕),只是它有必要的连接来调整缓冲的窗口为ostream要求提供更多(以及更多)数据。

if (f)有效,因为ifstreaman overload for operator bool,当ifstream的“真实性”被测试时会隐式调用,告诉您文件是否处于失败状态

答案 1 :(得分:2)

首先回答你的第一个问题:

std::ifstream属于std::ifstream f {...}分配的类型,但这是一种相当愚蠢的写作方式。人们通常会写operator bool ()。流有一个重载的!fail(),它会为您提供.rdbuf()

至于第二个问题:streambuf返回的是stringstream stream个对象。返回时,此对象不包含整个文件内容。相反,它提供了访问数据的接口,ruby { code => "fields = event.get('portsIp').split(',') event.set('portsIpArray',fields)" } 使用此接口。

答案 2 :(得分:1)

auto f = std::ifstream{file};

f的类型为std::ifstream

stream << f.rdbuf();

std::ifstream维护一个缓冲区,您可以通过f.rdbuf()获取该缓冲区,并且它不会一次性加载整个文件。在调用上述命令时发生加载,stringstream将从该缓冲区中提取数据,ifstream将在缓冲区用完数据时执行加载。

您可以使用setbuf手动设置缓冲区大小。