ファイル

■ファイルの種類

	ファイルには大きく分けてテキストファイルとバイナリファイルの2種類があります。
	
		・テキストファイル
			文字として読めるもの
			(ソースファイルやHTMLファイルなど)

		・バイナリファイル
			0と1の数値の集まりで文字として読めないファイル
			(画像ファイルやサウンドファイルなど)

■ファイル処理の基本

	C言語でファイルを扱うにはファイルポインタという専用の型を使用します。
	このファイルポインタを使用してファイルの読み書きを行います。
	
		●ファイルポインタの宣言の書式:
			FILE *変数名;

	ファイルを扱う時は必ず次の手順で行います。
		「①ファイルを開く」
		「②読み書きを行う」
		「③ファイルを閉じる」

■ファイルを開く

	ファイルを開くにはfopen_s関数を使用します。

	fopen関数書式:
		error_no fopen_s(FILE **fp, ファイル名, オープンモード);

	仕様:
		fopen関数は引数に指定したファイル名のファイルを
		オープンモードの内容で開きます。

	戻り値:
		ファイルオープンに成功したら0が返り、
		失敗したら非0が返ります。
		失敗時の値はエラー番号となるので、
		その値を使用してエラーを内容を確認します。

	第一引数(ファイルポインタのアドレス):
		オープンしたFILEを格納するFILEポインタのアドレスを指定します。
		オープンが成功したらここに非NULLの値が入り、
		失敗したらNULLが入ります。
		

	第二引数(ファイル名):
		ファイル名は相対パスと絶対パスのどちらかで指定します。
			相対パス:
				実行ファイルから見たファイルパスのこと

			絶対パス:
				フォルダ階層の頂点から目的のファイルまでのパスのこと

	第三引数(オープンモード):
		オープンモードはテキストファイルとしてオープンする設定と
		バイナリファイルとしてオープンする設定があります。

			テキストファイルとしてオープンするための設定:
				"r":読み出し専用
				"w":書き出し専用
				"a":追加書き込み

			バイナリファイルとしてオープンするための設定:
				"rb":読み出し専用
				"wb":書き出し専用
				"ab":追加書き込み

			オープンモードのファイルの開始位置:
				読み出しモード:先頭
				書き出しモード:先頭
				追加書き込みモード:末尾

■テキストファイルの読み込み

テキストファイルの読み込みを行う場合、オープンモードは"r"を指定し、
読み込みの関数はfgets関数を使用します。

●fgets関数
	・書式:
		fgets(文字列格納用配列, 読み込み最大文字数, ファイルポインタ);

	・fgets仕様:
		ファイルポインタから1行分、
		または読み込み最大文字数分の文字列を読み込みます。
			
	・第一引数(文字列格納用配列):
		char型の文字列配列を用意して、それを指定します。
			
	・第二引数(読み込み最大文字数)
		fgetsで取得できる最大の文字数を指定します。

	・第三引数(ファイルポインタ)
		ファイルオープンで返されたファイルポインタを指定します。

●読み込みの流れ
	ファイルの読み込みはファイルの先頭から開始します。
	fgetsなどの読み込み関数を使用したら読み込みが終了した次の場所まで
	ファイルポインタの位置が移動します。

	C_0051

●読み込み終了の判定
	ファイル読み込みの終了を判断する方法ですが、
	読み込んだ位置がEOF(End Of File)かどうかで判断します。
	EOFとはファイルの終端をあらわす定数のことで、
	stdio.hで宣言してあります。

	fgetsの場合は関数の戻り値を利用するか、
	自分でファイルポインタがEOFか判断します。
	
	・fgetsの戻り値を調べる場合
		FILE *fp = NULL;
		char list[16];
		
		fopen_s(&fp, "test.txt", "r");

		if (fp != NULL)
		{
			while(fgets(list, 16, fp) != NULL)
			{
				printf("%s", list);
			}
			fclose(fp);
		}

		fgetsは読み込む内容がなければ
		NULLを返すのでそれを利用します。

	・自分でEOFか調べる場合
		FILE *fp = NULL;
		char list[16];

		fopen_s(&fp, "test.txt", "r");

		if (fp != NULL)
		{
			while(true)
			{
				fgets(list, 16, fp);
				printf("%s", list);

				if (feof(fp) != 0)
				{
					break;
				}
			}
			fclose(fp);
		}

		自分で調べる場合はfeof関数を使用します。
		feof関数にファイルポインタを渡すと
		ファイルポインタがEOFの場合は非0を返し、
		まだ読み込める場合は0を返すのでそれを利用します。
		※上記コードはファイルの最終行が空行だった場合、
		 正常に動作しないので注意して下さい。

■テキストファイルの書き出し

テキストファイルの書き出しを行う場合はファイルオープン関数の
オープンモードの設定を"w"、または"a"にします。
書き出しで使用する関数はfputsかfprintfを使用します。

●fputs関数
	書式:
		fputs(文字列, ファイルポインタ);

	仕様:
		引数のファイルポインタに文字列を書き出す

	第一引数(文字列):
		ファイルに書き出す文字列を指定します。

	第二引数(ファイルポインタ):
		書き出しを行うためのファイルポインタを指定します。

●fprintf関数
	書式:
		fprintf(fp, 文字列, 可変引数…);

	仕様:
		引数のファイルポインタに文字列を書き出します。
		書き出しに使用する文字列はprintfと同様に可変引数の部分を
		利用して汎用的な文字列を作成することが可能です。

	第一引数(ファイルポインタ):
		書き出しを行うためのファイルポインタを指定します。

	第二引数(文字列):
		ファイルに書き出す文字列を指定します。

	第三引数以降:
		第二引数の文字列に使用されている特殊文字を置換するための値

	具体例:
		FILE *fp = NULL;

		fopen_s(&fp, "test.txt", "w");

		if (fp != NULL)
		{
			fputs("fputs write\n", fp);

			fprintf(fp, "fprintf write = %d行目\n", 2);

			fclose(fp);
		}

■バイナリファイルの読み込み

バイナリファイルの読み込みはfread関数を使用して、
fopenのオープンモードでは"rb"を指定します。
バイナリファイルは改行など特殊文字も関係なくただの数値として扱います。

●fread関数
	書式:
		実際の読み込み回数 fread(バッファ, 1回で読み込むバイト数, 
						読み込み回数, ファイルポインタ);

	仕様:
		freadは1回で読み込むバイト数と読み込む回数を指定して
		ファイルからデータを読み込み、バッファに格納します。
		例えば 「fread(buff, 1, 10, fp)」の場合
		1バイトを10回読み込んでバッファに格納します。
		ですので、実質10バイト分がバッファに格納されることになります。
			
	戻り値:
		読み込みが成功したら第三引数で指定した値が返ります。
		失敗したら指定した第三引数で指定した値以外が返ってきます。

	第一引数(バッファ):
		読み込んだデータを格納するバッファを用意します。

		バッファ:
			データを保存するためのメモリ領域のこと
			C言語では配列やmallocでバッファを確保する

	・第二引数(1回で読み込むバイト数):
		1回で読み込むバイト数を指定します。
			
	・第三引数(読み込む回数):
		第二引数のバイト数を何回読み込むかを決めます。

	・第四引数(ファイルポインタ):
		読み込むためのファイルポインタを指定します。

	・具体例
		void main(void)
		{
			FILE *fp = NULL;

			fopen_s(&fp, "test.txt", "rb");

			if (fp != NULL)
			{
				char buff[128];

				memset(buff, 0, sizeof(char) * 128);
				// 128バイトを1回だけfpから読み込む
				fread(buff, sizeof(char) * 128, 1, fp);

				fclose(fp);
			}
		}

■バイナリファイルの書き出し

バイナリファイルの書き出しはfwrite関数を使用して、
fopenのオープンモードでは"wb"を指定します。
		
●fwrite関数
	書式:
		実際の書き込み回数 fwrite(バッファ, 1回で書き込むバイト数,
						書き込む回数, ファイルポインタ);
		
	仕様:
		1回で書き込むバイト数と書き込む回数を指定して、
		バッファの内容を分割して書き込みます。
		例えば 「fwrite(buff, 1, 16, fp)」の場合
		バッファの内容を1バイトずつに分割して16回書き込みます。

	戻り値:
		書き込みが成功したら第三引数で指定した値が返ります。
		失敗したら第三引数で指定した値以外の値が返ってきます。

	第一引数:
		ファイルに書き込むデータのバッファを指定します。

	第二引数:
		1回で書き込むバイト数を指定します。

	第三引数:
		第二引数で指定したバイト数を何回書き込むかの回数を指定します。

	第四引数:
		書き込むためのファイルのファイルポインタを指定します。

	具体例:
		FILE *fp = NULL;

		fopen_s(&fp, "test.txt", "wb");

		if (fp != NULL)
		{
			char test[32];

			for (int i = 0; i < 32; i++)
			{
				test[i] = i;
			}

			// 16バイトずつで2回書き込む
			fwrite(test, sizeof(char) * 16, 2, fp);

			fclose(fp);
		}

■ファイルを閉じる

ファイルを閉じるにはfclose関数を使用します。

●fclose関数
	書式:
		int fclose(ファイルポインタ);

	仕様:
		オープンしているファイルポインタを引数に渡すことで、
		ファイルを閉じることができます。
		
	戻り値:
		ファイルを閉じることに成功した場合は 0 を
		失敗した場合は EOF を返します。

	引数(ファイルポインタ):
		fopenを使用して取得したファイルポインタを指定します。

	具体例:
		FILE *fp = NULL;

		fopen_s(&fp, "test.txt", "r");

		if (fp != NULL)
		{
			fclose(fp);
		}