协慌网

登录 贡献 社区

在 C ++ 中使用 ifstream 逐行读取文件

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");

两种标准方法是:

  1. 假设每一行都由两个数字组成,并逐个令牌读取令牌:

    int a, b;
    while (infile >> a >> b)
    {
        // process pair (a,b)
    }
  2. 基于行的解析,使用字符串流:

    #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; ,但是oofstream代表output 。如果要从文件(输入)读取,请使用ifstream 。如果您想同时读写,请使用fstream

可以通过 C ++ 逐行读取文件。

[快速] 使用 std :: getline()循环

最简单的方法是打开 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 的 file_description_source

另一种可能性是使用 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 语言。此代码的速度可以比上述 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

在此处输入图片说明