[C言語] CSVファイルを読み込む方法をわかりやすく解説

C言語でCSVファイルを読み込むには、まずファイルを開くためにfopen関数を使用します。

次に、fgets関数を用いてファイルから1行ずつデータを読み込みます。

読み込んだ行をstrtok関数でカンマ区切りに分割し、各フィールドを取得します。

この方法を用いることで、CSVファイルの各行を効率的に処理することが可能です。

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

この記事でわかること
  • CSVファイルをC言語で読み込む基本的な手順
  • ファイルのオープンとエラーチェックの方法
  • データの分割と型変換の実践例
  • 複数のCSVファイルを一括で処理する方法
  • CSVデータを構造体に格納する応用技術

目次から探す

CSVファイルの読み込み手順

ファイルのオープンとエラーチェック

CSVファイルを読み込む際には、まずファイルを開く必要があります。

C言語ではfopen関数を使用してファイルを開きます。

ファイルが正常に開けたかどうかを確認するために、NULLチェックを行います。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r"); // ファイルを読み込みモードで開く
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1; // エラーコードを返す
    }
    // ファイル処理
    fclose(file); // ファイルを閉じる
    return 0;
}

このコードでは、data.csvというファイルを読み込みモードで開き、開けなかった場合にはエラーメッセージを表示します。

行単位でのデータ読み込み

ファイルを開いた後は、fgets関数を使用して行単位でデータを読み込みます。

fgetsは指定したバッファに1行分のデータを読み込みます。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    char buffer[1024]; // 行データを格納するバッファ
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    while (fgets(buffer, sizeof(buffer), file)) {
        printf("読み込んだ行: %s", buffer); // 読み込んだ行を表示
    }
    fclose(file);
    return 0;
}

このコードは、data.csvから1行ずつデータを読み込み、コンソールに表示します。

デリミタによるデータの分割

CSVファイルの各行はカンマで区切られたデータで構成されています。

strtok関数を使用して、カンマをデリミタとしてデータを分割します。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    char buffer[1024];
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    while (fgets(buffer, sizeof(buffer), file)) {
        char *token = strtok(buffer, ","); // カンマで分割
        while (token != NULL) {
            printf("データ: %s\n", token); // 分割されたデータを表示
            token = strtok(NULL, ",");
        }
    }
    fclose(file);
    return 0;
}

このコードは、各行をカンマで分割し、個々のデータを表示します。

データの型変換と格納

CSVファイルから読み込んだデータは文字列として扱われます。

必要に応じて、atoiatof関数を使用して整数や浮動小数点数に変換します。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    char buffer[1024];
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    while (fgets(buffer, sizeof(buffer), file)) {
        char *token = strtok(buffer, ",");
        while (token != NULL) {
            int number = atoi(token); // 文字列を整数に変換
            printf("整数データ: %d\n", number);
            token = strtok(NULL, ",");
        }
    }
    fclose(file);
    return 0;
}

このコードは、CSVファイルから読み込んだ文字列データを整数に変換し、表示します。

データの型に応じて適切な変換を行い、プログラム内で利用します。

実践例:CSVファイルの読み込みプログラム

サンプルCSVファイルの準備

まず、CSVファイルを用意します。

この例では、sample.csvという名前のファイルを作成し、以下のようなデータを含めます。

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

このCSVファイルは、名前、年齢、職業の3つの列から構成されています。

コードの実装

次に、C言語でこのCSVファイルを読み込むプログラムを実装します。

以下のコードは、sample.csvを読み込み、各行のデータを分割して表示します。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file = fopen("sample.csv", "r");
    char buffer[1024];
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    // ヘッダー行を読み飛ばす
    fgets(buffer, sizeof(buffer), file);
    while (fgets(buffer, sizeof(buffer), file)) {
        char *name = strtok(buffer, ",");
        char *age = strtok(NULL, ",");
        char *occupation = strtok(NULL, ",");
        if (name && age && occupation) {
            printf("名前: %s, 年齢: %s, 職業: %s\n", name, age, occupation);
        }
    }
    fclose(file);
    return 0;
}

このプログラムは、sample.csvを開き、ヘッダー行を読み飛ばした後、各行のデータをカンマで分割して表示します。

実行結果の確認

上記のプログラムを実行すると、以下のような結果が得られます。

名前: 田中太郎, 年齢: 30, 職業: エンジニア
名前: 鈴木花子, 年齢: 25, 職業: デザイナー
名前: 佐藤次郎, 年齢: 40, 職業: マネージャー

この結果は、sample.csvの各行のデータが正しく読み込まれ、分割されて表示されていることを示しています。

プログラムは、CSVファイルの各行をカンマで分割し、名前、年齢、職業をそれぞれの変数に格納して出力しています。

応用例

複数のCSVファイルを一括で読み込む

複数のCSVファイルを一括で読み込む場合、ファイル名を配列に格納し、ループを使用して各ファイルを順次開いて処理します。

以下のコードは、複数のCSVファイルを読み込む例です。

#include <stdio.h>
#include <string.h>
int main() {
    const char *filenames[] = {"file1.csv", "file2.csv", "file3.csv"};
    char buffer[1024];
    for (int i = 0; i < 3; i++) {
        FILE *file = fopen(filenames[i], "r");
        if (file == NULL) {
            printf("%sを開けませんでした。\n", filenames[i]);
            continue;
        }
        // ヘッダー行を読み飛ばす
        fgets(buffer, sizeof(buffer), file);
        while (fgets(buffer, sizeof(buffer), file)) {
            printf("%s: %s", filenames[i], buffer); // ファイル名と行データを表示
        }
        fclose(file);
    }
    return 0;
}

このプログラムは、file1.csvfile2.csvfile3.csvの3つのファイルを順に開き、各ファイルのデータを読み込んで表示します。

CSVファイルの特定列のみを抽出する

CSVファイルから特定の列のみを抽出するには、strtok関数を使用して必要な列のデータを選択します。

以下のコードは、特定の列(例:年齢列)のみを抽出する例です。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file = fopen("sample.csv", "r");
    char buffer[1024];
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    // ヘッダー行を読み飛ばす
    fgets(buffer, sizeof(buffer), file);
    while (fgets(buffer, sizeof(buffer), file)) {
        strtok(buffer, ","); // 名前をスキップ
        char *age = strtok(NULL, ","); // 年齢を取得
        if (age) {
            printf("年齢: %s\n", age);
        }
    }
    fclose(file);
    return 0;
}

このプログラムは、sample.csvから年齢列のみを抽出して表示します。

CSVデータを構造体に格納する

CSVデータを構造体に格納することで、データをより扱いやすくすることができます。

以下のコードは、CSVデータを構造体に格納する例です。

#include <stdio.h>
#include <string.h>
typedef struct {
    char name[50];
    int age;
    char occupation[50];
} Person;
int main() {
    FILE *file = fopen("sample.csv", "r");
    char buffer[1024];
    Person people[100];
    int count = 0;
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    // ヘッダー行を読み飛ばす
    fgets(buffer, sizeof(buffer), file);
    while (fgets(buffer, sizeof(buffer), file) && count < 100) {
        char *name = strtok(buffer, ",");
        char *age = strtok(NULL, ",");
        char *occupation = strtok(NULL, ",");
        if (name && age && occupation) {
            strncpy(people[count].name, name, sizeof(people[count].name) - 1);
            people[count].age = atoi(age);
            strncpy(people[count].occupation, occupation, sizeof(people[count].occupation) - 1);
            count++;
        }
    }
    fclose(file);
    // 構造体に格納されたデータを表示
    for (int i = 0; i < count; i++) {
        printf("名前: %s, 年齢: %d, 職業: %s\n", people[i].name, people[i].age, people[i].occupation);
    }
    return 0;
}

このプログラムは、sample.csvのデータをPerson構造体に格納し、格納されたデータを表示します。

構造体を使用することで、データの管理が容易になります。

よくある質問

CSVファイルの読み込みでよくあるエラーは?

CSVファイルの読み込みでよくあるエラーには、以下のようなものがあります。

  • ファイルが存在しない: 指定したファイル名が間違っているか、ファイルが存在しない場合に発生します。

例:FILE *file = fopen("nonexistent.csv", "r");

  • ファイルの権限が不足している: 読み込み権限がないファイルを開こうとするとエラーになります。
  • データの形式が不正: CSVファイルのデータが期待する形式でない場合、データの分割や型変換でエラーが発生することがあります。

大きなCSVファイルを効率的に読み込むには?

大きなCSVファイルを効率的に読み込むためには、以下の方法を検討してください。

  • バッファサイズを調整する: fgetsで使用するバッファサイズを適切に設定し、メモリ使用量を最適化します。
  • メモリマッピングを使用する: mmapを使用してファイルをメモリにマッピングし、効率的にアクセスします(ただし、プラットフォーム依存のため注意が必要です)。
  • 並列処理を活用する: 複数のスレッドやプロセスを使用して、ファイルの異なる部分を同時に処理します。

CSVファイルの読み込み速度を改善する方法は?

CSVファイルの読み込み速度を改善するためには、以下の方法を試してみてください。

  • I/O操作を最小限にする: 一度に多くのデータを読み込むことで、ディスクI/Oの回数を減らします。
  • データのキャッシュを利用する: 頻繁にアクセスするデータをメモリにキャッシュして、再読み込みを防ぎます。
  • 効率的なデータ構造を使用する: データを格納する際に、効率的なデータ構造を選択して、アクセス速度を向上させます。

まとめ

CSVファイルの読み込みは、C言語でデータを扱う上で基本的なスキルです。

この記事では、CSVファイルの読み込み手順から応用例までを詳しく解説しました。

これを機に、CSVファイルを扱うプログラムを実際に作成し、理解を深めてみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • 標準入出力 (47)
  • ファイル (76)
  • URLをコピーしました!
目次から探す