使用stringstream

时间:2018-04-05 22:04:06

标签: c++ fstream ifstream stringstream

我需要两次逐行读取文件。文件内容应该适合内存。因此,我通常会将整个文件读入缓冲区,然后使用该缓冲区。

但是,由于我想使用std::getline,我需要使用std::basic_istream。所以,我认为写

是个好主意
std::ifstream file(filepath);
std::stringstream ss;
ss << file.rdbuf();

for (std::string line; std::getline(ss, line);)
{
}

但是,我不确定这里到底发生了什么。我猜ss << file.rdbuf(); 将文件读入ss的任何内部缓冲区。实际文件访问权限应仅在std::getline(ss, line);发生。

因此,通过提供表单的第二个for循环,我应该再次阅读整个文件。那效率很低。

我是否正确,因此需要提出另一种方法?

3 个答案:

答案 0 :(得分:2)

  

我猜ss << file.rdbuf();没有将文件读入任何内部   ss的缓冲区。实际文件访问应该只发生在   std::getline(ss, line);

这是不正确的。 cppreference.com有关于operator<<重载的说法:

basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb); (9)
     

9)表现为UnformattedOutputFunction。构造并检查sentry对象后,检查sb是否为空指针。如果是,则执行setstate(badbit)并退出。否则,从sb控制的输入序列中提取字符并将其插入*this,直到满足以下条件之一:

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

如果未插入任何字符,请执行setstate(failbit)。如果在解压缩时抛出异常,请设置failbit,如果在failbit中设置了exceptions(),则重新抛出异常。

所以你的假设不正确。 file的全部内容被复制到ss控制的缓冲区,因此从ss读取不会访问文件系统。您可以随意阅读ss,并根据需要多次回头,而不会产生每次重读文件的开销。

答案 1 :(得分:0)

在第一个循环之后,清除EOF和失败位并返回到stringstream的开头:

ss.clear();
ss.seekg(0, std::ios::beg);

答案 2 :(得分:0)

  

我是否正确,因此需要提出另一种方法?

你不对。 “hense”也是没有根据的。问题中没有足够的信息,但我怀疑问题与使用流缓冲区无关。

在不知道第一个“垃圾”字符是什么的情况下,我不能肯定地说,但我怀疑该文件是宽字符的unicode格式,并且您正在使用不适用于宽字符的访问操作。如果是这种情况,缓冲文件与问题无关。

作为实验,请尝试以下操作。记住这个。

foreach j in speechunderstandibility speechacceptability hypernasality { 
recode `j' (0 = 3) (3 = 0) (1 = 2) (2 = 1), gen (`j'_1)
}

foreach j in hyponasality audibleemission {
recode `j' (0 = 1) (1 = 0), gen (`j'_1)
}

如果前四个数字是255 254 92 0或255 254 47 0,我不会感到惊讶。

这可能会有所帮助:Problem using getline with unicode files