fread() はストリームの「現在位置」からデータを読み込む。任意の位置のデータを読み込むためにはこの「現在位置」を動かしてやる必要がある。
fseek() はそのための関数だ。
int fseek(FILE *ストリーム, long オフセット, int 開始位置);
fseek() は「開始位置」から「オフセット」バイトだけ「現在位置」を移動する。「開始位置」は次のマクロのどれかでなければいけない。
SEEK_SET | ファイルの先頭から |
SEEK_CUR | 現在位置から |
SEEK_END | ファイルの終わりから |
これらのマクロは stdio.h で定義されている。
fseek() は成功すると 0 を返し、失敗すると 0 以外の値を返す。
ところで、ファイルの現在位置を知りたいときは ftell() を使う。
long ftell(FILE *ストリーム);
ftell() は成功すると現在位置を返し、失敗すると -1 を返す。
次のプログラムは、10 個のデータ(double型)をファイルに書き込み、ファイルを開き直す。そして何番目のデータを表示したいかをユーザーに尋ねて、それを表示する。
#include <stdio.h> #include <stdlib.h> double d[10] = { 10.23, 19.87, 1002.23, 12.9, 0.897, 11.45, 75.34, 0.0, 1.01, 875.875 }; int main(void) { long loc; double value; FILE *fp; /* write array data */ if ((fp = fopen("myfile", "wb")) == NULL) { printf("Cannot open file.\n"); exit(1); } if (fwrite(d, sizeof d, 1, fp) != 1) { printf("Error: at writing.\n"); exit(1); } fclose(fp); /* re-open file */ if ((fp = fopen("myfile", "rb")) == NULL) { printf("Cannot open file.\n"); exit(1); } printf("What number of element? [0-9] "); scanf("%ld", &loc); if (fseek(fp, loc * sizeof(double), SEEK_SET)) { printf("Seek error.\n"); exit(1); } fread(&value, sizeof(double), 1, fp); printf("Element %ld is %f\n", loc, value); fclose(fp); return 0; }
47 行目で fseek() を使っている。loc に double 型のサイズをかけて、移動すべきバイト数を求めている。
実行例:
takatoh@nightschool $ ./sample_9_6 What number of element? [0-9] 4 Element 4 is 0.897000