*目次 [#s1fa2c14]

#contents


*fopen関数の特徴 [#q05a7be2]

-FILEを作成するためにはfopen関数が用いられる。
-_readは__sreadという関数を代入している。

[補講]stdioに関係するユーザーに見えない関数の名前は「__s」から始まっている。例えば、__srget()の動きを知りたいなら、rget.cのソース内の__srget()のところを読めばよい。 ◇

*テクニック [#ec6758f8]

**ファイル名の指定 [#e4aecd8f]

 文字列定数内の「\」はエスケープシーケンスという特別な意味があるので、文字列定数内で「\」という文字を表したい場合は「\\」のようにして使う。

↓悪い例

 if ((fp = fopen("C:\work\sample.dat", "rb")) == NULL) {…}

↓よい例

 if ((fp = fopen("C:\\work\\sample.dat", "rb")) == NULL) {…}

**ファイルの存在を調べる [#o5b29273]

 処理系特有の関数を使わなくてもfopen関数を使えば実現できる。fopen関数で第2引数に'''既存ファイルが存在しなければエラーとする'''文字列(例:rやrbなど)を設定しておく。そして、fopen関数の戻り値がNULLであればファイルが存在しないという処理を行えばよい。

#code(c){{
#include <stdio.h>
#include <stdlib.h>

int main(){
	FILE *fp;

	if ((fp = fopen("sample.txt", "r")) == NULL) {
		printf("File Open Error\n");
		exit(1);
	}
	fclose(fp);
	printf("File Exist\n");
	return 0;
}
}}

**ファイルのサイズを調べる [#y5005b16]

***ファイルを開いて読み込む [#dcc8bc8e]

 ファイルを開かないでファイルのサイズを取得する標準関数はANSI Cの規格には存在しない。よって、ファイルを開いて読み込むという処理を行いながら、サイズを求めるのが一般的である。

***stat関数を利用する [#pb6f7a9e]

 UNIXならばstat関数が用意されている。これを利用したプログラムを次に示す。

#code(c){{
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(){
	struct stat buf;	/* ファイル情報の格納領域 */

	if ((stat("sample.c", &buf)) != 0) {
		perror("ファイルの情報は取得できませんでした。\n");
		exit(1);
	}
	printf("ファイルの大きさ: %ld バイト\n", buf.st_size);
	printf("更新時刻        : %s\n", ctime(&buf.st_atime));
	return 0;
}
}}

[補講]MS VC++ならば_stat関数などがある。 ◇

 いずれにせよこうした処理系依存の関数を使用すると、移植性が低くなってしまう。

*バイナリモードが存在する理由 [#m47544cc]

 UNIXでは改行は「LF」の1バイトで済むのに対して、DOSやWindowsでは改行は「CR+LF」の2バイトが必要である。

|''OS''|''行終端''|''16進数''|
|DOS,Windows|<CR>+<LF>|0x0D0A|
|UNIX|<LF>|0x0A|
|Mac OS|<CR>|0x0D|

 UNIXの場合も問題ないが、DOSではgetchar関数やgetc関数が単純に1バイトずつストリームから読むと問題が起きる。そこで、DOSでCを実現する際に、ファイルから読み込む際に裏で「CR+LF」を「LF」に変換するという方針を採用している。そして、出力の際には逆向きの変換を行っている。fopen関数のr,rbフラグでテキスト(ASCII)ファイルであるかバイナリファイルであるかを判断できるため、うまく処理できるのである。

 こうした変換を行う仕様はテキストファイルを読むときには必要だが、バイナリファイルを読むときには不要といえる。なぜならば、バイナリファイルにたまたま「CR+LF」が登場するときに勝手に変換されてしまうと困ってしまう。そこで、バイナリファイルを読み書きするときのために、テキストモードの他にバイナリモードが用意されているのである。


*参考文献 [#xd8095d6]

-『Q&A100で学ぶ!Cプログラミング』
-『デーモン君のソース探検』
-『C言語体当たり学習徹底入門』
-『C実践プログラミング 第3版』