file.txt 的内容是:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
其中5 3
是一个坐标对。如何在 C ++ 中逐行处理此数据?
我可以获取第一行,但是如何获取文件的下一行?
ifstream myfile;
myfile.open ("file.txt");
首先,创建一个ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
两种标准方法是:
假设每一行都由两个数字组成,并逐个令牌读取令牌:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
基于行的解析,使用字符串流:
#include <sstream>
#include <string>
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
int a, b;
if (!(iss >> a >> b)) { break; } // error
// process pair (a,b)
}
您不应该混合使用(1)和(2),因为基于令牌的解析不会吞噬换行符,因此,如果在基于令牌的提取使您进入代码后getline()
行的末尾。
使用ifstream
从文件中读取数据:
std::ifstream input( "filename.ext" );
如果您确实需要逐行阅读,请执行以下操作:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
但是您可能只需要提取坐标对:
int x, y;
input >> x >> y;
更新:
在您的代码中,您使用ofstream myfile;
,但是o
在ofstream
代表output
。如果要从文件(输入)读取,请使用ifstream
。如果您想同时读写,请使用fstream
。
可以通过 C ++ 逐行读取文件。
最简单的方法是打开 std :: ifstream 并使用 std :: getline()调用循环。该代码是干净的,易于理解。
#include <fstream>
std::ifstream file(FILENAME);
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
file.close();
}
另一种可能性是使用 Boost 库,但是代码变得更加冗长。性能与上面的代码(带有 std :: getline()的循环)非常相似。
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
namespace io = boost::iostreams;
void readLineByLineBoost() {
int fdr = open(FILENAME, O_RDONLY);
if (fdr >= 0) {
io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
io::stream <io::file_descriptor_source> in(fdDevice);
if (fdDevice.is_open()) {
std::string line;
while (std::getline(in, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
fdDevice.close();
}
}
}
如果性能对您的软件至关重要,则可以考虑使用 C 语言。此代码的速度可以比上述 C ++ 版本快 4-5 倍,请参见下面的基准测试
FILE* fp = fopen(FILENAME, "r");
if (fp == NULL)
exit(EXIT_FAILURE);
char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
// using printf() in all tests for consistency
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
我已经使用上面的代码完成了一些性能基准测试,结果很有趣。我已经使用包含 100,000 行,1,000,000 行和 10,000,000 行文本的 ASCII 文件测试了该代码。每行文字平均包含 10 个字。该程序使用-O3
优化进行编译,其输出转发到/dev/null
以便从测量中删除记录时间变量。最后但并非最不重要的是,每段代码都使用printf()
函数记录了每一行的一致性。
结果显示每段代码读取文件所花费的时间(以毫秒为单位)。
两种 C ++ 方法之间的性能差异很小,在实践中不应有任何区别。 C 代码的性能使基准测试令人印象深刻,并且可以在速度方面改变游戏规则。
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms