使用字符串流逐行读取文件两次
Read a file line-by-line twice using 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 循环,我应该再次阅读整个文件。这是低效的。
我是否正确,因此需要提出另一种方法?
我想
ss << file.rdbuf();
不会将文件读入任何内部ss
的缓冲液。实际文件访问应仅在以下位置进行std::getline(ss, line);
.
这是不正确的。 cppreference.com 对operator<<
过载有这样的说法:
basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb); (9)
9) 表现为未格式化的输出函数。构造并检查哨兵对象后,检查
sb
是否为空指针。如果是,则执行setstate(badbit)
并退出。否则,从sb
控制的输入序列中提取字符,并将其插入*this
,直到满足以下条件之一:
- 文件结尾出现在输入序列上;
- 在输出序列中插入失败(在这种情况下,不会提取要插入的字符);
- 发生异常(在这种情况下,将捕获异常)。
如果未插入任何字符,则执行
setstate(failbit)
。如果在提取时引发异常,则设置failbit
,如果在exceptions()
中设置failbit
异常,则重新引发异常。
所以你的假设是不正确的。file
的全部内容被复制到由ss
控制的缓冲区中,因此从ss
读取不会访问文件系统。 您可以自由地通读ss
并根据需要多次回到开头,而不会产生每次重新读取文件的开销。
在第一个循环之后,清除 EOF 和失败位,然后返回到stringstream
的开头,如下所示:
ss.clear();
ss.seekg(0, std::ios::beg);
我是否正确,因此需要提出另一种方法?
你说得不对。"母鸡"也是没有根据的。问题中没有足够的信息,但我怀疑问题与使用流缓冲区无关。
在不知道第一个"垃圾"字符是什么的情况下,我不能肯定地说,但我怀疑该文件是宽字符 unicode 格式,并且您正在使用不适用于宽字符的访问操作。如果是这种情况,缓冲文件与问题无关。
作为实验,请尝试以下操作。 注意w的。
std::wifstream file(filepath);
std::wstringstream ss;
ss << file.rdbuf();
for (int i = 0; i < 42; ++i) {
wchar_t ch;
ss >> ch;
std::cout << static_cast<unsigned>(ch) << ' ';
}
如果前四个数字是 255 25492 0 或 255 254 47 0,我不会感到惊讶。
这可能会有所帮助:将 getline 与 unicode 文件一起使用时出现问题
- C++两次从文件保存对象读取多重继承
- 带有文件结束函数的 while 循环重复输出文件中的最后一个数字两次
- 在循环工作时,首先将两个文件读为向量,但仅次于迭代一次
- 如何使用预处理器指令包含两次具有不同代码的文件?
- 使用字符串流逐行读取文件两次
- C OOP,读取文件的问题,EOF使用了两次,排行榜
- Qfiledialog:文件夹名称在Windows下方出现两次
- 是否值得两次通过文件进行迭代,以创建最小的数据结构
- 为什么输入文件的最后一行运行两次?
- 为什么在这里对c++输入文件流进行两次检查
- 锁定文件,避免使用相同的过程以访问两次
- 尽管 #ifndef,但包含两次头文件
- CppUnit 和 CMake:.cpp文件被编译两次
- 正在从文件中读取最后两次出现的内容
- 流将所有内容写入我的文件两次
- NodeJS 文件系统 监视抛出事件两次或更多次
- 我的文件正在输出到屏幕两次 C++
- 文件在add_custom_command后source_group中添加了两次
- 程序写入记录在 C++ 的二进制文件中两次
- C++ cout 字符'return'文件中的字符出现两次