ランダムアクセス

ランダムアクセス

ファイルを読み取る際、いちいち上から一行ずつ読んでいては時間がかかります。

例えば、100×100の行列を記憶したファイルから(80,1)の要素を読み取るとすれば、80行読み取る必要があります。

いきなり(80,1)を読み取れたら時間がかからなくて速いプログラムを作れます。

ここでは、ある特定の要素を読み取るランダムアクセスについて解説します。

ベクトルから要素を読み込む

では、ベクトル(1,2,3,4)をバイナリ形式でファイルに書き込み、要素2である「2」を読み込むプログラムをつくります。

すると以下のようになります。

#include <stdio.h>
#include <stdlib.h>

int data[4]={1,2,3,4};

int main(void){
	int i;
	FILE *fp;

	//書き込み処理
	if((fp=fopen("myfile","wb"))==NULL){
		printf("ファイルを開けませんでした\n");
		exit(1);
	}
	for(i=0;i<4;i++){
		if(fwrite(&data[i],sizeof(int),1,fp)!=1){	//data[i]を書き込む
			printf("書き込みエラー\n");
			exit(1);
		}
	}
	fclose(fp);

	//読み込み処理
	if((fp=fopen("myfile","rb"))==NULL){
		printf("ファイルを開けませんでした\n");
		exit(1);
	}
	if(fseek(fp,2*sizeof(int),SEEK_SET)){
		printf("ファイルを開けませんでした\n");
		exit(1);
	}
	fread(&i,sizeof(int),1,fp);
	printf("%d\n",i);
	fclose(fp);

	return 0;
}

実行結果は以下のようになります。

3

このプログラムではintサイズで1から4を書き込んでいます。

そして、 fseek(fp,2*sizeof(int),SEEK_SET) で、2*sizeof(int)の部分にセットしています。

fseek(ファイルポインタ,ファイルサイズ,読み方);

という命令でアクセスする場所を設定できます。

ここでSEEK_SETはファイルの先頭からという意味です。

つまり、ファイルの先頭から2*sizeof(int)の位置にセットしています。SEEK_SET以外にも

  • SEEK_SET:ファイルの先頭から
  • SEEK_CUR:現在の位置から
  • SEEK_END:ファイルの最後から

があります。状況に応じて使い分けましょう。

あと、fseekは成功すると0を返します。

 

また、読み取る際は fread(&i,sizeof(int),1,fp); で読み取ります。

sizeof(int)で1要素読み取りiに代入することを意味しています。

fread(代入する変数のアドレス,読み込み単位のサイズ,読み込み数,ファイルのポインタ);

が使い方です。

著者:安井 真人(やすい まさと)