fwrite と fread はレコード単位の I/O 関数であり、fread 関数と fwrite 関数は通常バイナリファイルの入出力に使用されます。
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
戻り値:読み取りまたは書き込みのレコード数。成功時は返されるレコード数が nmemb と等しくなります。エラーが発生した場合、またはファイルの末尾まで読み取った場合は、返されるレコード数が nmemb より小さくなり、0 を返すこともあります。
fread と fwrite はレコードの読み書きに使用されます。ここでのレコードとは、int、構造体、固定長配列などの固定長のバイト列を指します。引数 size は 1 つのレコードの長さを示し、nmemb は読み書きするレコード数を示します。これらのレコードは ptr が指すメモリ空間に連続して格納され、合計 size * nmemb バイトを占めます。fread はファイル stream から size * nmemb バイトを読み出して ptr に保存し、fwrite は ptr 内の size * nmemb バイトをファイル stream に書き込みます。
nmemb は読み取りまたは書き込みを要求するレコード数です。fread と fwrite が返すレコード数は、nmemb で指定したレコード数より小さくなる可能性があります。例えば、現在の読み書き位置がファイルの末尾までの距離がレコード 1 つ分しかない場合、fread を呼び出すときに nmemb を 2 と指定すると、戻り値は 1 になります。現在の読み書き位置がすでにファイルの末尾にある場合、またはファイル読み取り中にエラーが発生した場合は、fread は 0 を返します。ファイル書き込み中にエラーが発生した場合は、fwrite の戻り値は nmemb で指定した値より小さくなります。次の例は 2 つのプログラムから構成されており、1 つのプログラムは構造体をファイルに保存し、もう 1 つのプログラムはファイルから構造体を読み出します。
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
fwrite および fread の参考コード:
writerec.c ファイルのコード
/* -------------------writerec.c--------------- */
#include <stdio.h>
#include <stdlib.h>
struct record {
char name[10];
int age;
};
int main(void)
{
struct record array[2] = {{"Ken", 24}, {"Knuth", 28}};
FILE *fp = fopen("d:/test.txt", "w");
if (fp == NULL) {
perror("Open file recfile");
exit(1);
}
fwrite(array, sizeof(struct record), 2, fp);
fclose(fp);
return 0;
}
readrec.c ファイルのコード:
/* -------------------readrec.c----------------- */
#include <stdio.h>
#include <stdlib.h>
struct record {
char name[10];
int age;
};
int main(void)
{
struct record array[2];
FILE *fp = fopen("d:/test.txt", "r");
if (fp == NULL) {
perror("Open file recfile");
exit(1);
}
fread(array, sizeof(struct record), 2, fp);
printf("Name1: %s\tAge1: %d\n", array[0].name, array[0].age);
printf("Name2: %s\tAge2: %d\n", array[1].name, array[1].age);
fclose(fp);
return 0;
}
$ gcc writerec.c -o writerec $ gcc readrec.c -o readrec
生成されたファイル recfile は直接開くことができないことがわかりました。
原因:私たちは、ひとつのstruct record 構造体を 1 つのレコードとみなします。構造体にはパディングバイトがあるため、各レコードは 16 バイトを占め、2 つのレコードをファイルに書き込むと合計 32 バイトになります。このプログラムが生成する recfile ファイルはテキストファイルではなくバイナリファイルです。なぜなら、そこには文字型データだけでなく、整数型データ 24 と 28(od コマンドの出力では 8 進数で 030 と 034 と表示されます)も保存されているからです。
注意:ファイル内で構造体を直接読み書きするプログラムは移植性がありません。あるプラットフォームで writebin.c プログラムをコンパイルして実行し、生成された recfile ファイルを別のプラットフォームにコピーして、そのプラットフォームで readbin.c プログラムをコンパイルして実行しても、ファイルの内容を正しく読み出せるとは限りません。プラットフォームによってエンディアンが異なる可能性があり(そのため整数データの格納方法が異なる)、構造体のパディング方法も異なる可能性があるからです(そのため同じ構造体が占めるバイト数が異なる可能性があり、name メンバーの後の age メンバーの位置も異なる可能性があります)。readrec プログラムを使用してファイル recfile の内容を読み出すことで、writerec プログラムが確かにレコードを recfile に正常に書き込んだことがわかります。
recfile から読み出した内容は次のとおりです:
Name1: Ken Age1: 24 Name2: Knuth Age2: 28
fwrite と fread の応用例:
1. 文字列をファイルに書き込む:
char *str="hello,I am a test program!"; fwrite(str,sizeof(char),strlen(str),fp)
2. 文字配列をファイルに書き込む:
char str[]={'a','b','c','d','e'};
fwrite(str,sizeof(char),sizeof(str),fp)
3. 整数配列をファイルに書き込む:
int a[]={12,33,23,24,12};
まず配列の要素数 nmemb を計算し、その後
fwrite(a,sizeof(int),nmemb,fp)
注:プログラムが生成するファイルはテキストファイルではなくバイナリファイルです。そのため、マシンが異なると整数の表現が異なり、生成されたファイルを直接開くことはできません。fread 関数を使用して、データがファイルに書き込まれたかどうかを確認できます。
原文 URL:http://purpleroom.blog.sohu.com/133812394.html