在 C++ 中迭代流后返回到流的开头
Posted
技术标签:
【中文标题】在 C++ 中迭代流后返回到流的开头【英文标题】:Return to begining of stream after iterating over it in C++ 【发布时间】:2013-11-14 19:12:11 【问题描述】:我是这样计算文件行数的
n = count(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), '\n') + 1;
之后我想逐行阅读,但这不起作用,
while (!file.eof())
string row;
file >> row;
cout << row << endl;
因为我认为计数将位置移到了末尾。如果我重新打开文件它可以工作,但我想这是一个丑陋的解决方案。
有什么方法/成员函数可以回到起点吗?
【问题讨论】:
cin
接受控制台输入,它不从文件中读取!使用std::getline
看看是否可行。
对不起,我打错了。它将是文件 >> 行。
你对这些信息做了什么(计算的行号)?
seekg() 有效,谢谢,但为什么您建议另外调用 clear()?
以防 eof 由第一遍设置。
【参考方案1】:
“我这样计算文件的行数……之后我想逐行读取”
你可以同时做这两件事:
std::ifstream filestream("somefile.ext");
std::vector<std::string> lines;
std::string line;
while (std::getline(filestream, line))
lines.push_back(line);
std::cout << "file has " << lines.size() << " lines" << std::endl;
还要注意:
while (!file.eof())
std::string row;
file >> row;
... // doing something with row
不安全,因为>>
可能会到达文件末尾,或者可能会发生一些错误,因此循环体的其余部分不应依赖于它被正确读取。这是一个好方法:
std::string word;
while (file >> word)
... // doing something with row
实际上是逐字阅读(不是逐行)。
【讨论】:
大文件吃内存 '不安全,因为 >> 可能会到达文件末尾或可能发生一些错误,因此循环体的其余部分不应依赖于它被正确读取。 - 实际上提取一些字符并点击 eof 很好,没有 eof 会出现失败状态,不是。但是,'这是一个好方法:没问题。【参考方案2】:清除错误位的 istream 并返回文件的开头。这是否是您想要做的最佳方法是另一个问题,具体取决于您的实际目标。
int main(int argc, char *argv[])
ifstream file("file.txt");
int n = count(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), '\n') + 1;
file.clear();
file.seekg(0);
string row;
while (file >> row)
cout << row << endl;
return (0);
【讨论】:
【参考方案3】:如果您使用ifstream
遍历文件,您可以使用seekg
调整读取位置
例如:
std::ifstream file(...);
int linecount = 0;
while (!file.eof())
if (file.get() == '\n') ++linecount;
// Clear the eofbit. Not necessary in C++11.
file.setstate(0);
// Rewind to the beginning of the file.
file.seekg(0);
如果您使用的是cin
,那不是文件。所以你不能倒带。您可以存储每一行(如@LihO 建议的那样),或者重新处理您的处理,以便您遍历您的输入一次,同时计算行数。
【讨论】:
以上是关于在 C++ 中迭代流后返回到流的开头的主要内容,如果未能解决你的问题,请参考以下文章
解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题