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

アレサ 「今度はfseek関数で


第3引数にSEEK_ENDが用いられた場合


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


まずはいつもどおり


数値

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に保存しました。


そして


SEEK_ENDの位置が


どこにあたるかを


今、

バイナリファイルに格納されている

1

2

3

4

5

6

7

をもちいて説明いたします。」


ソーラー「では再び、お願い💖」


アレサ「はい😊


では、わかりやすく


SEEK_ENDの位置にあたる場所を図で表してみます。


図でみると


数値データ7の後の最後の位置が


SEEK_ENDの位置にあたります。」



最初の位置_________ <<<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🌞



アレサ 「SEEK_ENDは


最後のデータである7を格納している7行目のすぐ後の


最後の位置を表しています。」


ソーラー「は~い」



アレサ「ですから


fseek(fp,読み込み開始位置と読み取り基準となる位置の差(読み取り基準となる位置からどれくらい離れているかをあらわす。),読み取り基準となる位置);


      fseek(fp,-2*sizeof(int),SEEK_END);


と記述された場合は


第3引数の読み取り基準となる位置は


SEEK_ENDに設定されています。


次は第2引数を設定してみます。


第3引数の読み取り基準となる位置を


SEEK_ENDと設定した場合


fseek関数の第2引数は


次の例のように記述します。


例1.fseek(fp,-sizeof(int),SEEK_END)

例2.fseek(fp,-2*sizeof(int),SEEK_END)

例3.fseek(fp,-3*sizeof(int),SEEK_END)

例4.fseek(fp,-4,SEEK_END)

例5.fseek(fp,-8,SEEK_END)



などなど・・・


このように


第3引数の読み取り基準となる位置を


SEEK_ENDと設定した場合


SEEK_ENDから遡って


読み取り開始位置が指定されるため


第2引数にはマイナスの数値が記述されることになります



ですので


sizeof(int)には-2*や-3*などのマイナス数値がかけられています


ここで

-2*sizeof(int)=-8

-3*sizeof(int)=-12


を表しています


そしてSEEK_SETのときと同じように


sizeof(int)はint型のデータ格納容量4バイトの

を表し


sizeof(int)は4

2*sizeof(int)は8

3*sizeof(int)は12をあらわしています。



fseek関数の第2引数が-5*sizeof(int)となった場合


どのように読み込み開始位置が指定されるのかを


みていきましょう。



fseek(fp,-5*sizeof(int),SEEK_END);ならば


この命令文は


最後の位置SEEK_ENDからsizeof(int) 5個分の幅ほど前の位置を


読み取り開始位置に指定することを表しています。



図で示すなら😊😊😊😊😊😊😊の位置が


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


最初の位置_________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


ソーラー「👆このsizeof(int)=4バイトの容量を持つ


1行ごとに


数値

1

2

3

4

5

6

7

1つずつ格納されているのは先程のエピソードと同じわけなんだ」


アレサ「そうなんです。


数値

1

2

3

4

5

6

7

sizeof(int)=4バイトの容量を持つ1行に


1つずつ格納されています


ですので


fseek(fp,-5*sizeof(int),SEEK_END);


と表記し


数値7が格納されている行のすぐ後の


最後の位置にあたるSEEK_ENDから


sizeof(int) 5個分の幅,前の位置を


読み取り開始位置😊😊😊😊😊😊😊に指定すると


数値3が格納されている行の前の位置が


読み取り開始位置😊😊😊😊😊😊😊となります。



例2.fseek(fp,-6*sizeof(int),SEEK_END);


の命令文では


最後の位置にあたるSEEK_ENDから


sizeof(int) 6個分の幅,前の位置を


読み取り開始位置に指定しています。


図でしめすなら😊😊😊の位置が


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


最初の位置_________SEEK_SET

1行目     int(4バイト)

______________読み取り開始位置😊😊😊

2行目     int(4バイト)

______________

3行目     int(4バイト)

______________

4行目     int(4バイト)

______________

5行目     int(4バイト)

______________

6行目     int(4バイト)

______________

7行目     int(4バイト)

最後の位置_________SEEK_END



ソーラー「今度はSEEK_ENDが


読み取り基準の位置になったわけなんだね」


アレサ「はい、そして実際にfseek関数を使って


バイナリファイル内での


データ読み取り開始位置を指定してから


fread関数を使い


データを


読み取っていきたいとおもいます。



ここでは


   fseek(fp,-6*sizeof(int),SEEK_END);を


つかって


👇の図で表されているように


読み取り開始位置😊😊😊😊😊を2行目の前に指定します。



最初の位置_________SEEK_SET

1     int(4バイト)

______________読み取り開始位置😊😊😊😊😊

2     int(4バイト)

______________

3     int(4バイト)

______________

4     int(4バイト)

______________

5     int(4バイト)

______________

6     int(4バイト)

______________

7     int(4バイト)

最後の位置_________SEEK_END


では読み取り開始位置😊😊😊😊😊を


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


2から


2

3

4


と数値データを


バイナリファイルから読み込んで


コマンドプロンプト画面に表示してみたいと思います。


まずはいつもどおり


数値

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;

}


コンパイル結果

(EAZY IDECの場合)

(Visual Studioの場合)


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


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



数値

をバイナリデータに変換して


バイナリファイルに格納できました。



では

fseek(fp,-6*sizeof(int),SEEK_END);

を使って


読み取り開始位置を2の前に指定して


数値

2

3

4


をバイナリファイルからよびだしてみます。


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



#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,-6*sizeof(int),SEEK_END);

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


ソーラー「これも、成功している。😊


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

2からデータが


読み込まれ格納されているね。」


アレサ 「このように


配列hairetuの

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

には


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

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

と表示されています」


ソーラー 「めでたし、めでたし


なんかこれってCDプレーヤーでいうところの


スキップ再生にとてもよく似てるね


fseek関数の第2引数がsizeof(int)のように


正の数なら

SEEK_SETの位置からあとの位置へスキップしてデータ読み取りを開始


fseek関数の第2引数が-6*sizeof(int)のように


負の数なら


SEEK_ENDの位置から前へスキップしてデータ読み取りを開始


しているからね。」












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

作者を応援しよう!

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

応援したユーザー

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