file.txt文件的内容如下:

5 3
6 4
7 1
10 5
11 6
12 3
12 4

其中53是一个坐标对。 如何在c++中逐行处理这个数据?

我能够得到第一行,但是我如何得到文件的下一行呢?

ifstream myfile;
myfile.open ("file.txt");

当前回答

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

基准测试——哪个更快?

I have done some performance benchmarks with the code above and the results are interesting. I have tested the code with ASCII files that contain 100,000 lines, 1,000,000 lines and 10,000,000 lines of text. Each line of text contains 10 words in average. The program is compiled with -O3 optimization and its output is forwarded to /dev/null in order to remove the logging time variable from the measurement. Last, but not least, each piece of code logs each line with the printf() function for consistency.

结果显示了每段代码读取文件所花费的时间(单位为毫秒)。

两种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

其他回答

既然你的坐标是成对的,为什么不为它们写一个结构呢?

struct CoordinatePair
{
    int x;
    int y;
};

然后你可以为istreams写一个重载的提取操作符:

std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
    is >> coordinates.x >> coordinates.y;

    return is;
}

然后你可以把坐标文件直接读入一个向量,像这样:

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    char filename[] = "coordinates.txt";
    std::vector<CoordinatePair> v;
    std::ifstream ifs(filename);
    if (ifs) {
        std::copy(std::istream_iterator<CoordinatePair>(ifs), 
                std::istream_iterator<CoordinatePair>(),
                std::back_inserter(v));
    }
    else {
        std::cerr << "Couldn't open " << filename << " for reading\n";
    }
    // Now you can work with the contents of v
}

首先,创建一个ifstream:

#include <fstream>
std::ifstream infile("thefile.txt");

两种标准方法是:

假设每一行由两个数字组成,并逐标记读取: Int a, b; While (filile >> a >> b) { //进程对(a,b) } 基于行的解析,使用字符串流: # include < sstream > # include <字符串> std:: string行; While (std::getline(filile, line)) { std:: istringstream iss(线); Int a, b; 如果(!(iss >> a >> b)) {break;} //错误 //进程对(a,b) }

您不应该混淆(1)和(2),因为基于标记的解析不会占用换行符,所以如果在基于标记的提取已经到达一行末尾之后使用getline(),您可能会得到虚假的空行。

虽然不需要手动关闭文件,但如果文件变量的范围更大,那么这样做是个好主意:

    ifstream infile(szFilePath);

    for (string line = ""; getline(infile, line); )
    {
        //do something with the line
    }

    if(infile.is_open())
        infile.close();

使用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;,然而ofstream中的o代表输出。如果你想从文件中读取(输入)使用ifstream。如果你既想读又想写,请使用fstream。

这是将数据加载到c++程序中的通用解决方案,并使用readline函数。可以对CSV文件进行修改,但是这里的分隔符是一个空格。

int n = 5, p = 2;

int X[n][p];

ifstream myfile;

myfile.open("data.txt");

string line;
string temp = "";
int a = 0; // row index 

while (getline(myfile, line)) { //while there is a line
     int b = 0; // column index
     for (int i = 0; i < line.size(); i++) { // for each character in rowstring
          if (!isblank(line[i])) { // if it is not blank, do this
              string d(1, line[i]); // convert character to string
              temp.append(d); // append the two strings
        } else {
              X[a][b] = stod(temp);  // convert string to double
              temp = ""; // reset the capture
              b++; // increment b cause we have a new number
        }
    }

  X[a][b] = stod(temp);
  temp = "";
  a++; // onto next row
}