10.2 逐行读取与处理
一次性读取整个文件很简单,但真实文件可能很大。如果日志文件有几百万行,一次全部放进内存会很浪费。逐行读取每次只处理一行。
std::getline
std::getline 每次读取一行文本。它会去掉换行符,并返回可以放进 while 的 stream 状态。
cpp
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::ifstream input("quotes.txt");
std::string line;
while (std::getline(input, line)) {
std::cout << line << std::endl;
}
return 0;
}没有更多行时,std::getline(input, line) 会变成 false,循环停止。
C++ stream 是 RAII 对象。input 离开作用域时文件会自动关闭,即使作用域是因为异常提前离开也是如此。
正在加载概念检查...
基于 token 的读取
有些文件格式很简单,例如空白分隔的一组数字。提取运算符 >> 可以一次读取一个 token。
cpp
#include <fstream>
#include <iostream>
int main() {
std::ifstream input("numbers.txt");
int value;
int total = 0;
while (input >> value) {
total += value;
}
std::cout << "Total: " << total << std::endl;
return 0;
}当文件格式简单且由空白分隔时,可以使用 token 提取。需要完整控制每一行时,使用 std::getline。
正在加载交互实验...
正在加载概念检查...
拆分单词
下面的程序读取 quotes.txt,去掉每个单词两端的标点,并把清理后的单词写进 words.txt。示例 quotes.txt 内容如下:
text
Talk is cheap. Show me the code.
Code never lies, comments sometimes do.
Stay Hungry Stay Foolish.cpp
#include <cctype>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
std::string clean_word(std::string word) {
while (!word.empty() && std::ispunct(static_cast<unsigned char>(word.front()))) {
word.erase(word.begin());
}
while (!word.empty() && std::ispunct(static_cast<unsigned char>(word.back()))) {
word.pop_back();
}
return word;
}
int main() {
std::ifstream input("quotes.txt");
std::ofstream output("words.txt");
std::string line;
while (std::getline(input, line)) {
std::istringstream row(line);
std::string word;
while (row >> word) {
std::string cleaned = clean_word(word);
if (!cleaned.empty()) {
output << cleaned << '\n';
}
}
}
return 0;
}程序运行后,words.txt 变成:
text
Talk
is
cheap
Show
me
the
code
Code
never
lies
comments
sometimes
do
Stay
Hungry
Stay
Foolish正在加载概念检查...
正在加载本节练习...