ファイル

[C++] カンマ区切りやタブ区切りのCSVを読み込む方法

C++でカンマ区切りやタブ区切りのCSVを読み込むには、標準ライブラリの<fstream><sstream>を使用するのが一般的です。

std::ifstreamでファイルを開き、1行ずつstd::getlineで読み取ります。

その後、std::istringstreamを用いて行を分割し、カンマやタブを区切り文字として処理します。

区切り文字はstd::getlineの第3引数で指定可能です。

C++でCSVファイルを読み込む基本手順

CSV(Comma-Separated Values)ファイルは、データをカンマやタブで区切って保存する形式で、データの交換や保存に広く利用されています。

C++でCSVファイルを読み込むための基本的な手順を以下に示します。

1. 必要なライブラリのインクルード

C++でファイル操作を行うためには、<iostream><fstream>ライブラリを使用します。

これにより、ファイルの読み書きが可能になります。

2. ファイルを開く

CSVファイルを読み込むためには、std::ifstreamを使用してファイルを開きます。

ファイルが正常に開けたかどうかを確認することも重要です。

3. データの読み込み

ファイルを行単位で読み込み、各行をカンマやタブで分割してデータを取得します。

std::getlineを使用して行を読み込み、std::stringstreamを使って分割することが一般的です。

4. 読み込んだデータの処理

読み込んだデータを適切な形式に変換し、必要に応じて配列やベクターに格納します。

これにより、後でデータを簡単に操作できるようになります。

5. ファイルを閉じる

ファイルの読み込みが完了したら、必ずファイルを閉じることを忘れないようにしましょう。

これにより、リソースの無駄遣いを防ぎます。

以下に、これらの手順を実装したサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
int main() {
    std::ifstream file("data.csv"); // CSVファイルを開く
    if (!file.is_open()) { // ファイルが正常に開けたか確認
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    std::vector<std::vector<std::string>> data; // データを格納するベクター
    while (std::getline(file, line)) { // 行を読み込む
        std::stringstream ss(line);
        std::string value;
        std::vector<std::string> row; // 行データを格納するベクター
        while (std::getline(ss, value, ',')) { // カンマで分割
            row.push_back(value); // 行データに追加
        }
        data.push_back(row); // データ全体に追加
    }
    file.close(); // ファイルを閉じる
    // 読み込んだデータを表示
    for (const auto& row : data) {
        for (const auto& value : row) {
            std::cout << value << " "; // 各値を表示
        }
        std::cout << std::endl; // 行の終わり
    }
    return 0;
}
値1 値2 値3 
値4 値5 値6 
値7 値8 値9

このサンプルコードでは、data.csvというCSVファイルを読み込み、各行のデータをカンマで分割して表示しています。

ファイルの存在や内容に応じて、出力結果は異なる場合があります。

カンマ区切りのCSVを読み込む方法

カンマ区切りのCSVファイルは、データをカンマで区切って保存する一般的な形式です。

C++でカンマ区切りのCSVファイルを読み込む方法について、具体的な手順とサンプルコードを示します。

1. CSVファイルの準備

まず、カンマ区切りのCSVファイルを用意します。

以下のような内容のdata.csvファイルを作成してください。

名前,年齢,職業
田中,30,エンジニア
佐藤,25,デザイナー
鈴木,28,マネージャー

2. 必要なライブラリのインクルード

C++でファイルを操作するために、<iostream><fstream><sstream><vector><string>のライブラリをインクルードします。

これにより、ファイルの読み込みや文字列の操作が可能になります。

3. ファイルを開く

std::ifstreamを使用してCSVファイルを開きます。

ファイルが正常に開けたかどうかを確認することが重要です。

4. データの読み込みと分割

std::getlineを使用してファイルから行を読み込み、std::stringstreamを使ってカンマで分割します。

分割したデータは、ベクターに格納します。

5. 読み込んだデータの表示

読み込んだデータを表示することで、正しく読み込まれたかを確認します。

以下に、カンマ区切りのCSVファイルを読み込むサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
int main() {
    std::ifstream file("data.csv"); // CSVファイルを開く
    if (!file.is_open()) { // ファイルが正常に開けたか確認
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    std::vector<std::vector<std::string>> data; // データを格納するベクター
    while (std::getline(file, line)) { // 行を読み込む
        std::stringstream ss(line);
        std::string value;
        std::vector<std::string> row; // 行データを格納するベクター
        while (std::getline(ss, value, ',')) { // カンマで分割
            row.push_back(value); // 行データに追加
        }
        data.push_back(row); // データ全体に追加
    }
    file.close(); // ファイルを閉じる
    // 読み込んだデータを表示
    for (const auto& row : data) {
        for (const auto& value : row) {
            std::cout << value << " "; // 各値を表示
        }
        std::cout << std::endl; // 行の終わり
    }
    return 0;
}
名前 年齢 職業 
田中 30 エンジニア 
佐藤 25 デザイナー 
鈴木 28 マネージャー

このサンプルコードでは、data.csvというカンマ区切りのCSVファイルを読み込み、各行のデータをカンマで分割して表示しています。

ファイルの内容に応じて、出力結果は異なる場合があります。

タブ区切りのCSVを読み込む方法

タブ区切りのCSVファイルは、データをタブ文字で区切って保存する形式です。

この形式は、特にExcelなどの表計算ソフトでのデータのやり取りに便利です。

C++でタブ区切りのCSVファイルを読み込む方法について、具体的な手順とサンプルコードを示します。

1. タブ区切りのCSVファイルの準備

まず、タブ区切りのCSVファイルを用意します。

以下のような内容のdata.tsvファイルを作成してください。

名前	年齢	職業
田中	30	エンジニア
佐藤	25	デザイナー
鈴木	28	マネージャー

2. 必要なライブラリのインクルード

C++でファイルを操作するために、<iostream><fstream><sstream><vector><string>のライブラリをインクルードします。

これにより、ファイルの読み込みや文字列の操作が可能になります。

3. ファイルを開く

std::ifstreamを使用してタブ区切りのCSVファイルを開きます。

ファイルが正常に開けたかどうかを確認することが重要です。

4. データの読み込みと分割

std::getlineを使用してファイルから行を読み込み、std::stringstreamを使ってタブで分割します。

分割したデータは、ベクターに格納します。

タブ文字は\tで表現されます。

5. 読み込んだデータの表示

読み込んだデータを表示することで、正しく読み込まれたかを確認します。

以下に、タブ区切りのCSVファイルを読み込むサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
int main() {
    std::ifstream file("data.tsv"); // タブ区切りのCSVファイルを開く
    if (!file.is_open()) { // ファイルが正常に開けたか確認
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    std::vector<std::vector<std::string>> data; // データを格納するベクター
    while (std::getline(file, line)) { // 行を読み込む
        std::stringstream ss(line);
        std::string value;
        std::vector<std::string> row; // 行データを格納するベクター
        while (std::getline(ss, value, '\t')) { // タブで分割
            row.push_back(value); // 行データに追加
        }
        data.push_back(row); // データ全体に追加
    }
    file.close(); // ファイルを閉じる
    // 読み込んだデータを表示
    for (const auto& row : data) {
        for (const auto& value : row) {
            std::cout << value << " "; // 各値を表示
        }
        std::cout << std::endl; // 行の終わり
    }
    return 0;
}
名前 年齢 職業 
田中 30 エンジニア 
佐藤 25 デザイナー 
鈴木 28 マネージャー

このサンプルコードでは、data.tsvというタブ区切りのCSVファイルを読み込み、各行のデータをタブで分割して表示しています。

ファイルの内容に応じて、出力結果は異なる場合があります。

エラー処理と例外対応

C++でCSVファイルを読み込む際には、さまざまなエラーが発生する可能性があります。

これらのエラーに適切に対処することは、プログラムの信頼性を高めるために重要です。

ここでは、エラー処理と例外対応の方法について説明します。

1. ファイルオープン時のエラー処理

ファイルを開く際には、ファイルが存在しない、またはアクセス権がない場合にエラーが発生することがあります。

std::ifstreamを使用してファイルを開く際には、必ずファイルが正常に開けたかどうかを確認します。

2. 行の読み込み時のエラー処理

std::getlineを使用して行を読み込む際にも、ファイルの終端に達したり、読み込みエラーが発生することがあります。

これらのエラーを適切に処理するために、ループの条件を工夫する必要があります。

3. データの分割時のエラー処理

データを分割する際に、予期しない形式のデータが含まれている場合、プログラムがクラッシュする可能性があります。

分割したデータの数が期待した数と異なる場合には、エラーメッセージを表示することが重要です。

4. 例外処理の活用

C++では、例外処理を使用してエラーを管理することができます。

tryブロック内でエラーが発生した場合、catchブロックでそのエラーを捕捉し、適切な処理を行います。

これにより、プログラムが異常終了するのを防ぐことができます。

以下に、エラー処理と例外対応を含むサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <stdexcept> // 例外処理のためのライブラリ
int main() {
    std::ifstream file("data.csv"); // CSVファイルを開く
    if (!file.is_open()) { // ファイルが正常に開けたか確認
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    std::vector<std::vector<std::string>> data; // データを格納するベクター
    try {
        while (std::getline(file, line)) { // 行を読み込む
            std::stringstream ss(line);
            std::string value;
            std::vector<std::string> row; // 行データを格納するベクター
            while (std::getline(ss, value, ',')) { // カンマで分割
                row.push_back(value); // 行データに追加
            }
            // 行データの数が期待した数でない場合
            if (row.size() != 3) { // ここでは3列を期待
                throw std::runtime_error("行のデータ数が不正です。"); // 例外を投げる
            }
            data.push_back(row); // データ全体に追加
        }
    } catch (const std::runtime_error& e) { // 例外を捕捉
        std::cerr << "エラー: " << e.what() << std::endl; // エラーメッセージを表示
        file.close(); // ファイルを閉じる
        return 1;
    }
    file.close(); // ファイルを閉じる
    // 読み込んだデータを表示
    for (const auto& row : data) {
        for (const auto& value : row) {
            std::cout << value << " "; // 各値を表示
        }
        std::cout << std::endl; // 行の終わり
    }
    return 0;
}

このサンプルコードでは、ファイルを開く際のエラー処理、行の読み込み時のエラー処理、データの分割時のエラー処理を行っています。

また、行のデータ数が期待した数でない場合には例外を投げて捕捉し、エラーメッセージを表示しています。

これにより、プログラムの信頼性が向上します。

応用:CSVデータの加工と利用

CSVファイルから読み込んだデータは、そのまま表示するだけでなく、さまざまな方法で加工し、利用することができます。

ここでは、CSVデータの加工と利用の具体例をいくつか紹介します。

1. データのフィルタリング

特定の条件に基づいてデータをフィルタリングすることで、必要な情報だけを抽出することができます。

たとえば、年齢が30歳以上の人だけを抽出する場合のサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
int main() {
    std::ifstream file("data.csv"); // CSVファイルを開く
    if (!file.is_open()) {
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    std::vector<std::vector<std::string>> filteredData; // フィルタリングされたデータを格納するベクター
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string name, age, occupation;
        std::getline(ss, name, ',');
        std::getline(ss, age, ',');
        std::getline(ss, occupation, ',');
        // 年齢が30歳以上の場合
        if (std::stoi(age) >= 30) {
            filteredData.push_back({name, age, occupation}); // フィルタリングされたデータに追加
        }
    }
    file.close(); // ファイルを閉じる
    // フィルタリングされたデータを表示
    for (const auto& row : filteredData) {
        for (const auto& value : row) {
            std::cout << value << " "; // 各値を表示
        }
        std::cout << std::endl; // 行の終わり
    }
    return 0;
}
田中 30 エンジニア 
鈴木 28 マネージャー

2. データの集計

CSVデータを集計して、特定の情報をまとめることも可能です。

たとえば、職業ごとの人数を集計する場合のサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
int main() {
    std::ifstream file("data.csv"); // CSVファイルを開く
    if (!file.is_open()) {
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    std::map<std::string, int> occupationCount; // 職業ごとの人数を格納するマップ
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string name, age, occupation;
        std::getline(ss, name, ',');
        std::getline(ss, age, ',');
        std::getline(ss, occupation, ',');
        occupationCount[occupation]++; // 職業ごとの人数をカウント
    }
    file.close(); // ファイルを閉じる
    // 職業ごとの人数を表示
    for (const auto& entry : occupationCount) {
        std::cout << entry.first << ": " << entry.second << "人" << std::endl; // 職業と人数を表示
    }
    return 0;
}
エンジニア: 1人
デザイナー: 1人
マネージャー: 1人

3. データの書き出し

加工したデータを新しいCSVファイルに書き出すこともできます。

以下は、フィルタリングしたデータを新しいCSVファイルに書き出すサンプルコードです。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
int main() {
    std::ifstream inputFile("data.csv"); // 入力CSVファイルを開く
    if (!inputFile.is_open()) {
        std::cerr << "ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::ofstream outputFile("filtered_data.csv"); // 出力CSVファイルを開く
    if (!outputFile.is_open()) {
        std::cerr << "出力ファイルを開けませんでした。" << std::endl;
        return 1;
    }
    std::string line;
    while (std::getline(inputFile, line)) {
        std::stringstream ss(line);
        std::string name, age, occupation;
        std::getline(ss, name, ',');
        std::getline(ss, age, ',');
        std::getline(ss, occupation, ',');
        // 年齢が30歳以上の場合
        if (std::stoi(age) >= 30) {
            outputFile << line << std::endl; // フィルタリングされたデータを書き出す
        }
    }
    inputFile.close(); // 入力ファイルを閉じる
    outputFile.close(); // 出力ファイルを閉じる
    return 0;
}

このサンプルコードでは、data.csvから年齢が30歳以上のデータをフィルタリングし、filtered_data.csvに書き出しています。

4. データの可視化

CSVデータを加工した後、可視化ツールを使用してグラフやチャートにすることもできます。

たとえば、集計したデータをExcelやPythonのMatplotlibなどで可視化することで、データの傾向を把握しやすくなります。

これらの応用例を通じて、CSVデータを効果的に加工し、さまざまな目的に利用することができます。

データのフィルタリング、集計、書き出し、可視化を組み合わせることで、より価値のある情報を引き出すことが可能です。

実践例:簡単なCSVリーダーの作成

ここでは、C++を使用して簡単なCSVリーダーを作成する実践例を紹介します。

このリーダーは、指定されたCSVファイルを読み込み、内容を表示する機能を持っています。

基本的なエラー処理やデータの分割も含まれています。

1. プログラムの概要

このCSVリーダーは、以下の機能を持ちます。

  • CSVファイルを指定して読み込む
  • 各行をカンマで分割し、データを表示する
  • ファイルが存在しない場合や読み込みエラーが発生した場合のエラー処理

2. 必要なライブラリのインクルード

プログラムには、ファイル操作や文字列処理のために以下のライブラリをインクルードします。

  • <iostream>:標準入出力
  • <fstream>:ファイル入出力
  • <sstream>:文字列ストリーム
  • <vector>:動的配列
  • <string>:文字列操作

3. サンプルコード

以下に、簡単なCSVリーダーのサンプルコードを示します。

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
int main() {
    std::string filename = "data.csv"; // 読み込むCSVファイル名
    std::ifstream file(filename); // CSVファイルを開く
    // ファイルが正常に開けたか確認
    if (!file.is_open()) {
        std::cerr << "ファイルを開けませんでした: " << filename << std::endl;
        return 1;
    }
    std::string line;
    std::vector<std::vector<std::string>> data; // データを格納するベクター
    // ファイルから行を読み込む
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string value;
        std::vector<std::string> row; // 行データを格納するベクター
        // カンマで分割
        while (std::getline(ss, value, ',')) {
            row.push_back(value); // 行データに追加
        }
        data.push_back(row); // データ全体に追加
    }
    file.close(); // ファイルを閉じる
    // 読み込んだデータを表示
    for (const auto& row : data) {
        for (const auto& value : row) {
            std::cout << value << " "; // 各値を表示
        }
        std::cout << std::endl; // 行の終わり
    }
    return 0;
}

4. プログラムの説明

  • ファイルのオープン: std::ifstreamを使用して指定されたCSVファイルを開きます。

ファイルが正常に開けなかった場合は、エラーメッセージを表示してプログラムを終了します。

  • データの読み込み: std::getlineを使用してファイルから行を読み込み、std::stringstreamを使ってカンマで分割します。

分割したデータは、行ごとにベクターに格納されます。

  • データの表示: 読み込んだデータを二重ループで表示します。

外側のループは行を、内側のループは各行の値を表示します。

5. 実行結果

このプログラムを実行すると、指定したdata.csvファイルの内容がコンソールに表示されます。

たとえば、以下のような内容のdata.csvファイルがあるとします。

名前,年齢,職業
田中,30,エンジニア
佐藤,25,デザイナー
鈴木,28,マネージャー

実行結果は次のようになります。

名前 年齢 職業 
田中 30 エンジニア 
佐藤 25 デザイナー 
鈴木 28 マネージャー

この簡単なCSVリーダーの作成を通じて、C++でのファイル操作やデータの分割、エラー処理の基本を学ぶことができました。

このプログラムを基に、さらに機能を追加したり、データの加工や集計を行うことができます。

CSVデータを扱う際の基礎として、ぜひ活用してみてください。

まとめ

この記事では、C++を使用してCSVファイルを読み込む方法や、カンマ区切りおよびタブ区切りのデータの処理、エラー処理や例外対応、データの加工と利用、さらには簡単なCSVリーダーの作成について詳しく解説しました。

これらの知識を活用することで、データ処理の効率を向上させることができるでしょう。

今後は、実際のプロジェクトやデータ分析において、これらの技術を積極的に取り入れてみてください。

関連記事

Back to top button