在 C++ 中读取 CSV 文件

Jinku Hu 2023年10月12日
在 C++ 中读取 CSV 文件

本文将说明几种如何在 C++ 中读取 CSV 文件的方法。

使用 std::getlinestd::istringstream 读取 C++ 中的 CSV 文件

CSV 文件通常称为文本文件格式,其中的值在每行中用逗号分隔。行称为数据记录,每条记录通常包含多个字段,以逗号分隔。CSV 格式主要用于存储表格数据,因此每个记录中包含相等数量的逗号分隔符。但是请注意,由于实际上有多种实现,因此可能会发现例如以逗号分隔的字段之间有空格,或者字段之间可能没有空格等。在以下示例中,我们假定之间没有空格田野。因此,逗号之间的每个字符都被视为一个数据单元。

首先,我们需要读取文件内容并将其存储在 std::string 对象中。readFileIntoString 函数利用 std::ostringstreamrdbuf 读取文件,并将 string 值返回给调用方函数。一旦上一步成功完成,我们就可以从字符串对象构造一个 std::istringstream,并在每行上进行迭代。在此迭代中,我们放置了另一个循环以提取一行中的每个字段,并将它们存储在 std::vector 中。在每行迭代结束时,我们将 vector 存储在 std::map 中,并清除 vector 进行下一个循环。请注意,std::map 可以替换为向量的向量或对特定情况最佳的任何其他自定义数据结构。

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>

using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;
using std::ostringstream;
using std::string;

string readFileIntoString(const string& path) {
  auto ss = ostringstream{};
  ifstream input_file(path);
  if (!input_file.is_open()) {
    cerr << "Could not open the file - '" << path << "'" << endl;
    exit(EXIT_FAILURE);
  }
  ss << input_file.rdbuf();
  return ss.str();
}

int main() {
  string filename("grades.csv");
  string file_contents;
  std::map<int, std::vector<string>> csv_contents;
  char delimiter = ',';

  file_contents = readFileIntoString(filename);

  istringstream sstream(file_contents);
  std::vector<string> items;
  string record;

  int counter = 0;
  while (std::getline(sstream, record)) {
    istringstream line(record);
    while (std::getline(line, record, delimiter)) {
      items.push_back(record);
    }

    csv_contents[counter] = items;
    items.clear();
    counter += 1;
  }

  exit(EXIT_SUCCESS);
}

外部的 while 循环使用默认定界符(换行符)调用 getline,而内部的循环将逗号字符指定为第三个参数。与前面的示例代码相反,下一个示例代码实现了一种解决方案,以处理字段中的尾随空格并解析数据单元,然后再将其存储在向量中。因此,在调用 push_back 之前,我们在内部的 while 循环中添加了 erase-remove 习惯用法。因为我们将 isspace 函数对象用作 remove_if 参数,所以它将处理任何空格字符,例如空格、制表符、回车符和其他字符。

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>

using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;
using std::ostringstream;
using std::string;

string readFileIntoString(const string& path) {
  auto ss = ostringstream{};
  ifstream input_file(path);
  if (!input_file.is_open()) {
    cerr << "Could not open the file - '" << path << "'" << endl;
    exit(EXIT_FAILURE);
  }
  ss << input_file.rdbuf();
  return ss.str();
}

int main() {
  string filename("grades.csv");
  string file_contents;
  std::map<int, std::vector<string>> csv_contents;
  char delimiter = ',';

  file_contents = readFileIntoString(filename);

  istringstream sstream(file_contents);
  std::vector<string> items;
  string record;

  int counter = 0;
  while (std::getline(sstream, record)) {
    istringstream line(record);
    while (std::getline(line, record, delimiter)) {
      record.erase(std::remove_if(record.begin(), record.end(), isspace),
                   record.end());
      items.push_back(record);
    }

    csv_contents[counter] = items;
    items.clear();
    counter += 1;
  }

  exit(EXIT_SUCCESS);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook

相关文章 - C++ File