fseek関数を用いてバイナリファイルからデータの読み込み開始位置を指定してからデータを読みこんでみましょう 読み取り基準位置がSEEK_CURの場合

アレサ 「今度はfseek関数で


第3引数にSEEK_CURを使い


fseek(fp,sizeof(int),SEEK_CUR)と記述された場合について


プログラムがどのような動作をしていくかみていきます。」


ソーラー「fseek関数の 第3引数がSEEK_CURと記述された場合の


解説スタートしま~す。


カメラさんこっち、こっち


真紅の美女がここにいます。


それではよろしくお願いしま~~~す。😊


アレサ「はいっ ソーラーさん


実はSEEK_CURシステムは簡単です。


では


また 準備として


数値データ


1

2

3

4

5

6

7


バイナリファイルに


セッティングするところから


はじめます。


まずはいつもどおり


数値

1

2

3

4

5

6

7


fwrite関数を使ってバイナリファイルに保存してみます


そのプログラムは次のようになります。


#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

fp=fopen("TEN-GOGO-C-language.bin","wb");

if(fp==NULL){

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int hairetu[]={1,2,3,4,5,6,7};


fwrite(&hairetu[0],sizeof(int),1,fp);

fwrite(&hairetu[1],sizeof(int),1,fp);

fwrite(&hairetu[2],sizeof(int),1,fp);

fwrite(&hairetu[3],sizeof(int),1,fp);

fwrite(&hairetu[4],sizeof(int),1,fp);

fwrite(&hairetu[5],sizeof(int),1,fp);

fwrite(&hairetu[6],sizeof(int),1,fp);


fclose(fp);

return 0;

}


コンパイル結果

Hello!ファイルオープンに成功しましたよ~ん



アレサ「ファイルオープンに成功しました💖


そして

fp=fopen("TEN-GOGO-C-language.bin","wb");

のオープンモード"wb"と

fwrite関数のはたらきにより


数値

バイナリファイルである

TEN-GOGO-C-language.binに保存できました。」


ソーラー「いいよ~😊その調子」


アレサ

「では次に


fseek(fp,sizeof(int),SEEK_SET);


を使って


読み取り開始位置を図で示されるように


2を格納している2行目の前😊😊😊😊😊😊😊に指定し



最初の位置_________SEEK_SET(読み取り基準位置)

1     sizeof(int)=4バイト

______________😊😊😊😊😊😊😊

2     sizeof(int)=4バイト

______________

3     sizeof(int)=4バイト

______________

4     sizeof(int)=4バイト

______________

5     sizeof(int)=4バイト

______________

6     sizeof(int)=4バイト

______________

7     sizeof(int)=4バイト

最後の位置_________SEEK_END



数値2からfread関数を使って


配列宣言

int hairetu[3];

により生成された

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

数値

2

3

4

格納してみます


そして

hairetu[0]

hairetu[1]

hairetu[2]

に格納された

数値

2

3

4

printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

をおこない

コマンドプロンプト画面にprintf出力表示してみます


そのプログラムは次のようになります。」



#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

fp=fopen("TEN-GOGO-C-language.bin","rb");

if(fp==NULL){

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");

int hairetu[3];


fseek(fp,sizeof(int),SEEK_SET);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);


fclose(fp);

return 0;

}


コンパイル結果


Hello!ファイルオープンに成功しましたよ~ん

2

3

4


アレサ「このように

fseek(fp,sizeof(int),SEEK_SET);

fseek関数の


第2引数に

sizeof(int)=4


第3引数に

SEEK_SET


を記述することにより


👇の図のように



最初の位置_________SEEK_SET(読み取り基準位置)

1     sizeof(int)=4バイト

______________😊😊😊😊😊😊😊

2     sizeof(int)=4バイト

______________

3     sizeof(int)=4バイト

______________

4     sizeof(int)=4バイト

______________

5     sizeof(int)=4バイト

______________

6     sizeof(int)=4バイト

______________

7     sizeof(int)=4バイト

最後の位置_________SEEK_END




読み取り開始位置を2行目の前の😊😊😊😊😊😊😊に指定することができました。


そして


fread関数をもちいて


2から


2

3

4

hairetu[0]

hairetu[1]

hairetu[2]

に格納し

printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

により


コマンドプロンプト画面に

2

3

4


表示することができました。」



ソーラー「ここからだね🌞🌞🌞🌞🌞🌞🌞🌞」



アレサ「はいっ もちろんですの。


ではまいります





     『TEN-GOGO天国にいける-C-言語入門技』





         


     『STILL GO TO HEAVEN天国にいけるまで





        


          

         『 EFE簡単に素敵に説明しよ










ソーラー「絶好調だね。アレサ


ここで・・・」


アレサ 「ここで次は

数値

2

3

4

につづいて


数値

をfread関数を使って配列に格納していきたいのですが・・・」


ソーラー「

新たに5から読み取りを開始し

5

6

7

とデータを配列に格納したいんだね。」


アレサ「ここでSEEK_CURが登場します。


さきほど

数値

2

3

4

がfread関数を使って配列に格納されました。


このとき


最後に読み取られた4を格納している4行目の後


5行目の前の位置が


SEEK_CURの位置となります


最初の位置_________SEEK_SET

1     sizeof(int)=4バイト

______________

2     sizeof(int)=4バイト

______________

3     sizeof(int)=4バイト

______________

4     sizeof(int)=4バイト

______________😊SEEK_CUR😊

5     sizeof(int)=4バイト

______________

6     sizeof(int)=4バイト

______________

7     sizeof(int)=4バイト

最後の位置_________SEEK_END



つまり

😊SEEK_CUR😊の位置は


SEEK_SETや

SEEK_ENDのように

はじめから

決まっているのでなく


最後に読み取られたデータを格納している行の後が


😊SEEK_CUR😊の位置となります。

 


例えば



バイナリファイル内のデータ

1

2

3

4

5

6

7

のうち


5だけを


fread関数で  


読み込んで用意した配列に格納したとします。


すると

😊SEEK_CUR😊の位置は


図で示される位置になります。

  


最初の位置_________ <<<SEEK_SET

1     int(4バイト)

______________

2     int(4バイト)

______________

3     int(4バイト)

______________

4     int(4バイト)

______________

5     int(4バイト)

______________😊SEEK_CUR😊の位置

6     int(4バイト)

______________

7     int_(4バイト)

最後の位置_________<<<SEEK_END



つまり


今の場合は


最後にfread関数を使って数値5を読み取り、配列に格納したことになるのですが


😊SEEK_CUR😊の位置は


その最後に配列に読み取った数値5を


格納している5行目のあとに移動します。


そしてまた新たに


fread関数で  


数値1だけを読み取り配列に格納したならば 


😊SEEK_CUR😊の位置は図で示される位置となります

  



最初の位置_________ <<<SEEK_SET

1     int(4バイト)

______________😊SEEK_CUR😊の位置

2     int(4バイト)

______________

3     int(4バイト)

______________

4     int(4バイト)

______________

5     int(4バイト)

______________

6     int(4バイト)

______________

7     int_(4バイト)

最後の位置_________<<<SEEK_END


このように


最後にfread関数によって読み込まれ配列に格納された数値1を


格納している行の後に


😊SEEK_CUR😊の位置が移動するのです。



また新しくプログラムを構成し


fread関数を用い


2

3

4


を読み込み配列に格納したなら



図の位置に


😊SEEK_CUR😊の位置は移動します


最初の位置_________ <<<SEEK_SET

1     int(4バイト)

______________

2     int(4バイト)

______________

3     int(4バイト)

______________

4     int(4バイト)

______________😊SEEK_CUR😊の位置

5     int(4バイト)

______________

6     int(4バイト)

______________

7     int_(4バイト)

最後の位置_________<<<SEEK_END



😊SEEK_CUR😊の位置は


最後にfread関数によって読み込まれた4を格納している


4行目の後


5行目の前に移動しています。


ソーラー「なんと😊SEEK_CUR😊の位置って


いろいろかわってくるんだね。」


アレサ「はいっ 


そして


😊SEEK_CUR😊の位置から


ファイルデータを読み込みたいときには


fseek関数の第3引数に


SEEK_CURをもちいます


その際は


データを😊SEEK_CUR😊の位置から


ずらして読み込む必要がないので


fseek関数の第2引数の値を0にします。


つまり 次の命令文のように記述するのでなく


fseek(fp,sizeof(int),SEEK_CUR);


SEEK_CURの位置から読み取りをすぐ開始するように

sizeof(int)の値を0にし


fseek(fp,0,SEEK_CUR);と記述します。



fseek(fp,sizeof(int),SEEK_CUR);

と読み込み開始位置を指定すると


😊SEEK_CUR😊の位置から sizeof(int)1つ分


後ろのデータから読み込みを開始するようになります。


それでは


さきほどのプログラム

👇


#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

fp=fopen("TEN-GOGO-C-language.bin","rb");

if(fp==NULL){

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");

int hairetu[3];


fseek(fp,sizeof(int),SEEK_SET);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);


fclose(fp);

return 0;

}

コンパイル結果


Hello!ファイルオープンに成功しましたよ~ん

2

3

4



命令文

fseek(fp,0,SEEK_CUR);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

を追加して


2

3

4

につづいて

5

6

7

fread関数によって読み込まれ

コマンドプロンプト画面に

表示されるよう


プログラムを作成、コンパイルしてみますね。😊


そのプログラムは次のようになります。」



#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

fp=fopen("TEN-GOGO-C-language.bin","rb");

if(fp==NULL){

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");

int hairetu[3];


fseek(fp,sizeof(int),SEEK_SET);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);


/*この時点で😊SEEK_CUR😊の位置は

4行目の後 5行目の前に移動しています。*/


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);



fseek(fp,0,SEEK_CUR);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);


/*ですのでfseek(fp,0,SEEK_CUR);

により

😊SEEK_CUR😊の位置である

4行目の後 5行目の前が


読み取り開始位置に指定されます。

つまり

fread関数を使って

数値5から

数値の読み取り、配列への格納が始まります

*/


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);


fclose(fp);

return 0;

}

アレサ「このプログラムをコンパイルすると


コンパイル結果

Hello!ファイルオープンに成功しましたよ~ん

2

3

4

5

6

7

となります。」


ソーラー「やったね、アレサ 


すごいなあ


素敵なお嬢さん」


アレサ「このプログラムでは


配列int hairetu[3]内の

配列変数

hairetu[0]

hairetu[1]

hairetu[2]


まず最初に


fread関数によって読み込まれた


バイナリファイルの数値データ


2

3

4

hairetu[0]=2

hairetu[1]=3

hairetu[2]=4


と格納され


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);


により


コマンドプロンプト画面に

2

3

4

がprintf出力表示されていきます。


この時点で


😊SEEK_CUR😊の位置は


最後にfread関数によって読み込まれた4を格納している


4行目の後 5行目の前に移動しています。


ですから


fseek(fp,0,SEEK_CUR);


が行われると


fread関数の読み込み開始位置は


4行目の後 

数値5を格納している


5行目の前になります。


ですので

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);

により

読み取りが開始されると


5

6

7


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[0]=2

hairetu[1]=3

hairetu[2]=4

から

hairetu[0]=5

hairetu[1]=6

hairetu[2]=7

へと上書きされ

格納されていきます


そして

printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

により


コマンドプロンプト画面に

2

3

4

に続いて


5

6

7


printf出力表示されていきます


その結果コンパイル結果は

Hello!ファイルオープンに成功しましたよ~ん

2

3

4

5

6

7

となります。


ここで

int hairetu[3];

により

生成された

hairetu[0]

hairetu[1]

hairetu[2]

fseek(fp,sizeof(int),SEEK_SET);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);

で数値

2

3

4


を格納するときと

fseek(fp,0,SEEK_CUR);

fread(&hairetu[0],sizeof(int),1,fp);

fread(&hairetu[1],sizeof(int),1,fp);

fread(&hairetu[2],sizeof(int),1,fp);

で数値

5

6

7

を格納するとき


の両方で使用されています



まず

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[0]=2

hairetu[1]=3

hairetu[2]=4

数値が格納された状態から


hairetu[0]=5

hairetu[1]=6

hairetu[2]=7


と上書きされるかたちで


数値

5

6

7


が格納されているのですね。」


ソーラー 「数値をprintf出力表示するのに


同じ配列


int hairetu[3];をつかっているんだね。


このような優雅な


配列


の使い方があるんだね。


これでfseek関数の第3引数に


SEEK_CURを使った場合


fread

関数を使って


バイナリファイルのどの位置のデータから


読み込みが開始されるのかがわかったね」

  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます