在 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

不安全,因为&gt;&gt; 可能会到达文件末尾,或者可能会发生一些错误,因此循环体的其余部分不应依赖于它被正确读取。这是一个好方法:

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++ 中迭代流后返回到流的开头的主要内容,如果未能解决你的问题,请参考以下文章

readLine读取socket流的时候产生了阻塞

c++中重载输出操作符,为啥要返回引用

解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题

SpringCloudGateway限流后,默认返回429的改造:改302跳转或增加响应body

c++:从vector::insert返回迭代器

C++ STL list迭代器