C++ で CSV ファイルを読む

胡金庫 2023年10月12日
C++ で CSV ファイルを読む

この記事では、C++ で CSV ファイルを読み取る方法のいくつかの方法について説明します。

C++ で CSV ファイルを読み込むには std::getlinestd::istringstream を使う

CSV ファイルは一般にテキストファイル形式として知られており、値は各行でコンマで区切られます。行はデータレコードと呼ばれ、各レコードは通常、コンマで区切られた複数のフィールドで構成されます。CSV 形式は主に表形式のデータを格納するために使用されるため、各レコードに同数のコンマ区切り文字が含まれています。ただし、実際には複数の実装があるため、たとえば、コンマで区切られたフィールド間にスペースがある場合や、フィールド間にスペースがない場合などがあります。以下の例では、フィールド間にスペースがないと仮定します。したがって、コンマの間のすべての文字が 1つのデータユニットとみなされます。

まず、ファイルの内容を読み取り、std::string オブジェクトに保存する必要があります。readFileIntoString 関数は、std::ostringstreamrdbuf を使用してファイルを読み取り、string 値を呼び出し元の関数に返します。前の手順が正常に完了したら、string オブジェクトから std::istringstream を作成し、各行を反復処理できます。この反復では、別のループを配置して行の各フィールドを抽出し、それらを std::vector に格納します。すべての行の反復の終わりに、ベクトルstd::map に格納し、次のサイクルのためにベクトルをクリアします。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 を呼び出しますが、内側のループは、3 番目の引数としてコンマ文字を指定します。前のサンプルコードとは対照的に、次のサンプルコードは、フィールドの末尾のスペースを処理し、データユニットを解析してからベクトルに格納するソリューションを実装します。したがって、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);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C++ File