苦しんで覚えるC言語

バイナリファイルの読み書き


テキストとバイナリ


ファイルには様々な種類のものがありますが、最も基本的な区別として、
テキストかバイナリかという違いがあります。

全てのファイルは本質的にはバイナリファイルです。
バイナリを直訳すると、2進数という意味なのですが、
バイナリファイルとはその名の通り、2進数で記録されたファイル、
要するに、数値のみで記録されたファイルのことを意味します。

それに対して、テキストファイルは、文字列だけが記録されたファイルです。
コンピュータの中では、文字列といえども数値で表されているので、
テキストファイルも、本質的にはバイナリファイルです。
しかし、テキストファイルは文字列で記録されているため、
テキストエディタなどで修正を行うことが容易です。

バイナリファイルも、特定のエディタで閲覧・修正することが出来ますが、
全てのデータが数値の固まりになっているため、
中身を見ても、その意味が全くわかりません。
しかし、数値を直接書き込むため、サイズが少なく高速です。

一般に、取り扱いを容易にする必要がある場合はテキストファイル、
高速性が必要とされる場合にはバイナリファイルを利用することが多いようです

目次に戻る

ファイルの開閉


テキストであれ、バイナリであれ、ファイル操作の基本的な手順に変わりはありません。
バイナリファイルも、fopen関数、fclose関数を使って開閉します。
ファイル名、モードの指定方法も全く同じです。
ただし、バイナリファイルを開く時には、モード文字列の最後にbをつけます

ここまで説明したことがわかれば、バイナリファイルの開閉が出来ます。
次のプログラムは、test.datと言う名前のファイルを書き込みのために開く例です。

#include <stdio.h>

int main(void)
{
	FILE *file;
	file = fopen("test.dat","wb");
	fclose(file);
	return 0;
}
このプログラムを実行すると、test.datという名前のファイルが作成されます。
今回は開いただけなので、当然中身は空っぽです。
混同しても使える
実際には、バイナリで開いてもテキストデータを読み書き出来ますし、
逆も可能ですが、改行の扱いなどで不便な点が多くなります。

目次に戻る

ファイルへの書き込み


ファイルに数値を直接書き込むには、fwrite関数を使用します。
fwrite関数の使い方は、次の通りです。

fwrite(書き込む変数アドレス,1項目のサイズ,項目数,ファイルポインタ);
書き込む数値を変数に代入しておき、その変数のアドレスを指定します。
項目のサイズはsizeof演算子を使用して求めることが出来ます。
変数を書き込むだけなら、項目数はとりあえず1で構いません。
次のプログラムは、test.datファイルに 100という数値を書き込みます。

#include <stdio.h>

int main(void)
{
	int buf = 100;
	FILE *file;
	file = fopen("test.dat","wb");
	fwrite(&buf,sizeof(buf),1,file);
	fclose(file);
	return 0;
}
このプログラムを実行すると、test.datファイルに値が書き込まれますが、
この値は、一般的なテキストエディタで見ることは出来ません。
バイナリファイルを見るには、バイナリエディタが必要になります。
下記は筆者が愛用しているエディタです。
hgBed http://www.vector.co.jp/soft/win95/util/se081906.html

バイナリエディタを使用してファイルを開くと、次のようになります。
LSIC86 は16ビットコンパイラなので、数値は4バイトで書き込まれます。
その他のコンパイラは32ビットなので、8バイトで書き込まれます。
test.dat
LSIC86 64 00
その他 64 00 00 00
ほとんどのバイナリエディタでは、数値を16進数で表示します。
その為、100という数値は、64と表示されます。
リトルエンディアンとビッグエンディアン
数学では、100を16進数に変換すると、0064になります。
しかし、バイナリエディタで閲覧した結果では、6400になっています。
これは、インテル互換CPUの特徴で、リトルエンディアンと呼ばれる表現です。
この表現では、16進数を2桁ずつに区切り逆の順番で保存します。
一方、マッキントッシュでは IBM製のCPUを使用しており、
こちらは16進数の順番通りに表現される方式で、ビッグエンディアンと呼ばれます。
現在では、Macもインテル製のCPUを使っています
fwrite関数による書き込みでは、配列を1度で書き込むことも出来ます。
やり方は、変数の代わりに配列を指定するだけです。
次のプログラムは、配列の値を書き込むプログラムです。
覚えていますか
配列名は、式の中では先頭アドレスになるので、&をつけません。

#include <stdio.h>

int main(void)
{
	int buf[] = { 10,100,1000,10000 };
	FILE *file;
	file = fopen("test.dat","wb");
	fwrite(buf,sizeof(buf),1,file);
	fclose(file);
	return 0;
}
このプログラムを実行すると、test.datに値が書き込まれます。
バイナリエディタを使用してファイルを開くと、次のようになります。
test.dat
LSIC86 0A 00 64 00 E8 03 10 27
その他 0A 00 00 00 64 00 00 00 E8 03 00 00 10 27 00 00

目次に戻る

ファイルからの読み込み


ファイルの数値を直接読み込むには、fread関数を使用します。
fread関数の使い方は、次の通りです。

fread(読み込む変数のポインタ,1項目のサイズ,項目数,ファイルポインタ);
これを見ると、使い方はfwrite関数と同じであることがわかります。
次のプログラムは、test.datファイルから、int型の数値を読み込みます。

#include <stdio.h>

int main(void)
{
	int buf;
	FILE *file;
	
	file = fopen("test.dat","rb");
	fread(&buf,sizeof(buf),1,file);
	fclose(file);
	
	printf("%d\n", buf);
	
	return 0;
}
このプログラムの実行結果は、test.datファイルの内容によって変わりますが、
第3項で作成したプログラムによって書き込まれていた場合、次の通りになります。
test.datファイルの中身が次の通りだった場合、実行結果は次の通りになります。
test.dat
0A 00 00 00

10
fwrite関数と同様にして、配列を読み込むことも出来ます。

目次に戻る