fread関数:C言語でバイナリファイルを読み書きするためのチュートリアル


fread 関数は、C言語においてバイナリファイルからデータを効率的に読み込むために使用されます。バイナリファイルは、テキストファイルとは異なり、数値データをそのまま保存するファイル形式です。fread 関数は、ファイルポインタ、読み込むデータの要素サイズ、読み込む要素数、読み込むファイルポインタを引数として受け取り、読み込まれた要素数を返します。

fread 関数の詳細

size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
  • stream: 読み込み対象のファイルポインタ
  • count: 読み込む要素数
  • size: 読み込むデータの要素サイズ (バイト単位)
  • ptr: 読み込まれたデータが格納されるポインタ

fread 関数の動作

  1. fread 関数は、stream で指定されたファイルから size バイトのデータを ptr で指されるメモリ領域に読み込みます。
  2. 読み込まれたデータの要素数は count で指定されます。
  3. fread 関数は、正常に読み込まれた要素数を返します。
  4. ファイル末に到達した場合、またはエラーが発生した場合は、 fread 関数は 0 以下の値を返します。

fread 関数の利点

  • ファイルの読み込み位置を制御することができます。
  • 様々なデータ型を扱うことができます。
  • バイナリファイルから効率的にデータを読み込むことができます。

fread 関数の例

#include <stdio.h>

int main() {
  int data[10];
  FILE *fp;

  // ファイルを開く
  fp = fopen("data.bin", "rb");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルからデータを読み込む
  size_t read_count = fread(data, sizeof(int), 10, fp);
  if (read_count < 10) {
    printf("データを読み込めません\n");
    fclose(fp);
    return 1;
  }

  // 読み込んだデータを処理する
  for (int i = 0; i < 10; i++) {
    printf("%d ", data[i]);
  }

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

この例では、"data.bin" というバイナリファイルから 10 個の整数を読み込み、コンソールに出力します。

  • エラー処理を適切に行う必要があります。
  • ファイルの読み込み位置を制御するには、fseek 関数と組み合わせて使用する必要があります。
  • fread 関数はバイナリファイルでのみ使用できます。


整数データの読み込み

#include <stdio.h>

int main() {
  int data[10];
  FILE *fp;

  // ファイルを開く
  fp = fopen("data.bin", "rb");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルからデータを読み込む
  size_t read_count = fread(data, sizeof(int), 10, fp);
  if (read_count < 10) {
    printf("データを読み込めません\n");
    fclose(fp);
    return 1;
  }

  // 読み込んだデータを処理する
  for (int i = 0; i < 10; i++) {
    printf("%d ", data[i]);
  }

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

構造体データの読み込み

このコードは、"data.bin" というバイナリファイルから student 構造体のデータを読み込み、コンソールに出力します。

#include <stdio.h>

typedef struct {
  int id;
  char name[20];
  double score;
} student_t;

int main() {
  student_t student;
  FILE *fp;

  // ファイルを開く
  fp = fopen("data.bin", "rb");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルからデータを読み込む
  size_t read_count = fread(&student, sizeof(student_t), 1, fp);
  if (read_count < 1) {
    printf("データを読み込めません\n");
    fclose(fp);
    return 1;
  }

  // 読み込んだデータを処理する
  printf("ID: %d\n", student.id);
  printf("名前: %s\n", student.name);
  printf("点数: %lf\n", student.score);

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

文字列データの読み込み

このコードは、"data.bin" というバイナリファイルから NULL 文字で区切られた文字列を読み込み、コンソールに出力します。

#include <stdio.h>

int main() {
  char str[100];
  FILE *fp;

  // ファイルを開く
  fp = fopen("data.bin", "rb");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルからデータを読み込む
  size_t read_count = fread(str, sizeof(char), sizeof(str) - 1, fp);
  if (read_count < 0) {
    printf("データを読み込めません\n");
    fclose(fp);
    return 1;
  }

  // 読み込んだデータを処理する
  str[read_count] = '\0'; // NULL 文字を追加
  printf("%s\n", str);

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

ファイル全体を読み込む

このコードは、"data.bin" というバイナリファイルのすべての内容を読み込み、コンソールに出力します。

#include <stdio.h>

int main() {
  FILE *fp;
  long file_size;
  char *buffer;

  // ファイルを開く
  fp = fopen("data.bin", "rb");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルサイズを取得
  fseek(fp, 0, SEEK_END);
  file_size = ftell(fp);
  fseek(fp, 0, SEEK_SET);

  // ファイル内容を読み込むためのバッファを確保
  buffer = malloc(file_size + 1);
  if (buffer == NULL) {
    printf("メモリを確保できません\n");


fgetc 関数と fputc 関数

fgetc 関数は、ファイルから 1 文字ずつ読み込み、その文字を返します。fputc 関数は、ファイルに 1 文字ずつ書き込みます。これらの関数は、小さなデータや 1 文字ずつ処理する必要がある場合に適しています。

#include <stdio.h>

int main() {
  FILE *fp;
  char ch;

  // ファイルを開く
  fp = fopen("data.txt", "r");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルから文字を読み込む
  while ((ch = fgetc(fp)) != EOF) {
    printf("%c", ch);
  }

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

fscanf 関数と fprintf 関数

fscanf 関数は、ファイルから書式化されたデータを読み込みます。fprintf 関数は、ファイルに書式化されたデータを書き込みます。これらの関数は、フォーマットされたデータの読み書きに適しています。

#include <stdio.h>

int main() {
  FILE *fp;
  int num;
  char name[20];

  // ファイルを開く
  fp = fopen("data.txt", "r");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルからデータを読み込む
  fscanf(fp, "%d %s", &num, name);
  printf("数値: %d, 名前: %s\n", num, name);

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

fgets 関数と fputs 関数

fgets 関数は、ファイルから 1 行の文字列を読み込み、その文字列を返します。fputs 関数は、ファイルに 1 行の文字列を書き込みます。これらの関数は、テキストファイルの読み書きに適しています。

#include <stdio.h>

int main() {
  FILE *fp;
  char line[100];

  // ファイルを開く
  fp = fopen("data.txt", "r");
  if (fp == NULL) {
    printf("ファイルを開けません\n");
    return 1;
  }

  // ファイルから行を読み込む
  while (fgets(line, sizeof(line), fp) != NULL) {
    printf("%s", line);
  }

  // ファイルを閉じる
  fclose(fp);

  return 0;
}

カスタム関数

特定のニーズに合致する代替手段がない場合は、カスタム関数を作成することができます。カスタム関数は、fread 関数よりも柔軟性と制御性に優れていますが、開発とテストにはより多くの時間と労力が必要です。

  • コードの簡潔性
  • パフォーマンス要件
  • データの処理方法
  • 読み込むデータの種類と量