我需要两次逐行读取文件。文件内容应该适合内存。因此,我通常会将整个文件读入缓冲区,然后使用该缓冲区。
但是,由于我想使用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循环,我应该再次阅读整个文件。那效率很低。
我是否正确,因此需要提出另一种方法?
答案 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,我不会感到惊讶。