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