このドキュメントは http://icrus.org/c_language_beginers_course/ 上にあります.
15章では,テキストファイルのリード/ライトを行いました.テキストファイルは,テキストエディタで読めるなど,扱いやすいところがたくさんあり人間との相性は良いようです.しかし,ファイル容量が大きくなる,ファイル容量が大きくなるとリード/ライトに時間がかかる(データが大量になったとき顕著になります)など,短所も多くあります.本格的にファイルを扱うには,コンピュータと相性がいいバイナリーファイルのリード/ライトが必要です.そこでこの章では,バイナリーファイルのリード/ライトについて説明します.
01: #include <stdio.h>
02: #include <stdlib.h>
03: #include <process.h>
04: #define FILENAME "a:\\binfile.dat"
05: struct borth_day_list{
06: char name[20];
07: int year;
08: int month;
09: int day;
10: };
11: struct borth_day_list list;
12:
13: void main(void){
14: FILE *fp;
15: char str[50];
16: if( (fp=fopen( FILENAME, "ab" ))==NULL ){
17: printf( "file open error:%s\n", FILENAME );
18: exit(1);
19: }
20:
21: while(1){
22: printf("名前を入力して下さい(リターンのみで終了します.):\n");
23: gets( list.name );
24: if( list.name[0]=='\0' )
25: break;
26: printf("%sさんの生年月日を入力して下さい(例1995,9,30):\n",list.name );
27: gets( str );
28: while( sscanf( str, "%d,%d,%d", &list.year, &list.month, &list.day )!=3 ){
29: printf("%sさんの生年月日をもう一度入力して下さい(例1995,9,30):\n", list.name );
30: gets( str );
31: }
32: printf( "%s,%s-->ファイル\n", list.name, str );
33: if( fwrite( &list,sizeof(list), 1, fp )<1 ){
34: printf( "%s Write error", FILENAME );
35: exit(1);
36: }
37: }
38: if( fclose( fp )==EOF ){
39: printf( "file close error:%s\n", FILENAME );
40: exit(1);
41: }
42: }
05~10行→構造体struct borth_day_listを定義します.
16~19行→ファイルをオープンするときの決まり文句です.バイナリーファイルを追加でオープンしますから,ファイル名("a:\binfile.dat")とオープンモード("ab")でオープンします.
28~31行→間違った誕生日の入力の仕方をすると再入力を要求します.
33~36行目→関数fwrite()を使って変数list(型は構造体borth_day_list)をファイルポインタfpの指すファイルへ出力します.
コンパイル・実行すると次のよう表示されます.
名前を入力して下さい(リターンのみで終了します.):
常盤 貴子[リターン印]
常盤 貴子さんの生年月日を入力して下さい(例1995,9,30):
1972,4,30[リターン印]
常盤 貴子,1972,4,30-->ファイル
名前を入力して下さい(リターンのみで終了します.):
森田 和義[リターン印]
森田 和義さんの生年月日を入力して下さい(例1995,9,30):
1945,8[リターン印]
森田 和義さんの生年月日をもう一度入力して下さい(例1995,9,30):
1945,8,22[リターン印]
森田 和義,1945,8,22-->ファイル
名前を入力して下さい(リターンのみで終了します.):
[リターン印]
MS-DOSのTYPEコマンドではバイナリーファイルは見れません.バイナリーファイルを見るためのコマンドDUMPを使って作成したファイルの様子を見てみましょう.
A:\>DUMP A:\BINFILE.DAT
Dump Version 3.10
00000000 8F ED 94 D5 81 40 8B 4D-8E 71 00
00 00 00 00 00 常盤 貴子......
00000010 00 00 00 00 B4 07 04 00-1E 00 90
58 93 63 81 40 ....エ.....森田
00000020 98 61 8B 60 00 00 00 00-00 00 00
00 00 00 99 07 和義............
00000030 08 00 16 00
....
次に,同じこのプログラムを実行すると,データをつけ足していくことができます.
01: #include <stdio.h>
02: #include <stdlib.h>
03: #include <process.h>
04: #define FILENAME "a:\\binfile.dat"
05: struct borth_day_list{
06: char name[20];
07: int year;
08: int month;
09: int day;
10: };
11: struct borth_day_list list;
12:
13: char *seiza[]={ "月のデータがまちがい",
14: "山羊座", "水瓶座", "魚座",
15: "牡羊座", "牡牛座", "双子座",
16: "蟹座", "獅子座", "乙女座",
17: "天秤座", "蠍 座", "射手座" };
18: void main(void){
19: FILE *fp;
20: int get_seiza(int, int);
21: if( (fp=fopen( FILENAME, "rb" ))==NULL ){
22: printf( "file open error:%s\n",FILENAME );
23: exit(1);
24: }
25: while( fread(&list,sizeof(list),1,fp)==1 ){
26: printf( "%-14sさん%2d年%2d月%2d日生まれ\n", list.name, list.year, list.month, list.day );
27: printf( "%sです.\n", *( seiza + get_seiza( list.month, list.day ) ) );
28: }
29: if( fclose( fp )==EOF ){
30: printf( "file close error:%s\n", FILENAME );
31: exit(1);
32: }
33: getchar();
34: }
35:
36: int get_seiza( int month, int day ){
37: ~以下関数get_seiza()はプログラム例15-2と同一です~
38: }
05~10行→構造体struct borth_day_listを定義します.
21~24行→ファイルをオープンするときの決まり文句です.今回はデータファイルを読み出しますのでオープンモード"rb"にします.
25~28行ファイルが終了するまで繰り返します.
28行目→関数fread()を使ってファイルのデータを読み出します.listを1つずつ読み込み,読み込んだ個数を返します.ファイルの終わりに来ると戻り値として1を返せなくなりますので1以外の戻り値のときファイルの終わりとみなして,whileループを終わります.
26~27行→関数fread()は,そのまま変数list(型は構造体borth_day_list)を読み込めますので,そのメンバを用いて画面表示をさせます.
29~32行目→ファイルを閉じるときの決まり文句です.
コンパイル・実行すると次のよう表示されます.
常盤 貴子 さん
1972年 4月30日生まれ
牡牛座です.
森田 和義 さん
1945年 8月22日生まれ
獅子座です.
リターンキーを押すとプログラムは終了します.
プログラムは,プログラム例16-1を使って入力したデータファイルを読み出して,その誕生日から星座名を出力するものです.ファイルが終了するまでファイルのデータと星座名を出力します.
このドキュメントは http://icrus.org/c_language_beginers_course/ 上にあります.
2017,1 ssatoh@ 足立工科大学 工学部 情報通信工学科