C 言語 | 高度な機能 | ランダムアクセス - fseek(), ftell()

ファイルの先頭から順番にデータを読み書きする方法をシーケンシャルアクセスと呼ぶ。任意の位置へ移動し、必要な部分だけを読み書きする方法をランダムアクセスと呼ぶ。ここでは標準 C 関数を使ったランダムアクセスを説明する。

任意の位置から読み込む

通常のファイル入力は、先頭から末尾へ順番に進む。データを読み込むと、次の操作位置は自動的に進む。次に読み書きするバイト位置をファイル位置と呼ぶ。

通常のテキストデータにはシーケンシャルアクセスが効率的である。しかし、バイナリーファイルには異なる種類の情報が 1 つのファイルに連続して保存されることが多い。特定のバイト位置にある値だけが必要な場合、手前のデータをすべて読み込むのは効率的ではない。

ファイル位置を移動するには fseek() を使用する。

fseek() 関数

int fseek(FILE *stream, long offset, int origin);

stream には有効なファイルストリーム、offset には origin から移動するバイト数を指定する。

定数 意味
SEEK_CUR 現在のファイル位置
SEEK_SET ファイルの先頭
SEEK_END ファイルの末尾

fseek() は成功すると 0、失敗すると 0 以外を返す。

現在のファイル位置を取得するには ftell() を使用する。

ftell() 関数

long ftell(FILE *stream);

コード 1

#include <stdio.h>

int main() {
 char fileName[256];
 int fileIndex , text;
 FILE *file;

 printf("読み込むファイル名を指定してください>");
 scanf("%s" , fileName);
 printf("読み込み開始位置をバイト単位で指定してください。");
 scanf("%d" , &fileIndex);

 file = fopen(fileName , "rb");
 if (file == NULL) {
   fprintf(stderr , "ファイル操作でエラーが発生しました。\n");
   return 0;
 }

 fseek(file , fileIndex , SEEK_SET);
 printf("ファイル位置 %ld から読み込みます--\n" , ftell(file));

 while(1) {
   text = fgetc(file);
   if (feof(file)) break;
   printf("%c" , text);
 }

 printf("\n");
 fclose(file);
 return 0;
}

このプログラムはファイル名と読み込み開始位置を受け取る。SEEK_SET を指定し、ファイルの先頭から fileIndex バイト進んだ位置へ移動した後、残りのデータを文字として表示する。ランダムアクセスは、特にバイナリーデータを扱う場合に役立つ。