如何用C++20 ifstream按N长度右移读取含换行的文件内容
解决C++20中ifstream滑动窗口读取文件内容的问题
你的需求是读取文件所有字符(包括换行符),以长度N=3的滑动窗口输出,每次窗口向右移动1个字符,直到文件末尾。原代码存在几个关键问题导致无法正常工作:
- 使用
while (!file.eof())判断循环结束是常见错误,eof状态只有在尝试读取超出文件末尾时才会触发,会导致最后一次循环处理无效数据。 file.cur不能直接获取当前文件指针位置,正确的方式是调用file.tellg()。- 每次读取N个字符后回退指针再ignore的逻辑,在文件末尾附近会触发读取错误,且未处理读取不足N个字符的情况。
下面提供两种可行的实现方式:
方案一:一次性读取文件到内存处理(适合小文件)
这种方式逻辑简单直观,避免频繁的文件指针操作:
#include <fstream> #include <string> #include <iostream> #include <sstream> int main() { std::ifstream file("test.txt"); if (!file.is_open()) { std::cout << "文件未找到" << std::endl; return 1; } // 一次性读取整个文件内容到字符串(包含所有换行符) std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); const size_t nlen = 3; // 遍历每个起始位置,输出滑动窗口内容 for (size_t i = 0; i < content.size(); ++i) { // 取当前位置开始最多nlen个字符,避免超出文件长度 size_t take_len = std::min(nlen, content.size() - i); std::cout << content.substr(i, take_len) << '\n'; } return 0; }
方案二:流式维护滑动窗口(适合大文件)
如果文件体积较大,不想一次性加载到内存,可以用缓冲区维护滑动窗口:
#include <fstream> #include <string> #include <iostream> int main() { std::ifstream file("test.txt"); if (!file.is_open()) { std::cout << "文件未找到" << std::endl; return 1; } const size_t nlen = 3; std::string window; char c; // 先读取前nlen-1个字符初始化窗口 for (size_t i = 0; i < nlen - 1 && file.get(c); ++i) { window += c; } // 每次读入一个字符,补全窗口后输出,再滑动窗口 while (file.get(c)) { window += c; std::cout << window << '\n'; window.erase(window.begin()); // 移除窗口最左侧字符 } // 处理文件读完后窗口剩余的字符 while (!window.empty()) { std::cout << window << '\n'; window.erase(window.begin()); } return 0; }
两种方案都能正确捕获换行符,实现你需要的滑动窗口输出效果。
内容的提问来源于stack exchange,提问作者ThomasCodesThings
相关产品推荐
相关产品推荐

