FILEポインタ
C言語では、使用される各ファイルは、メモリ内の対応するファイル情報領域を開きます。この領域は、ファイルの関連情報(ファイルの名前、ファイルのステータス、ファイルの現在の場所など)を格納するために使用されます。 。)。この情報は構造変数に格納されます。構造タイプはシステムによって宣言され、FILEという名前が付けられます。たとえば、VS2008コンパイル環境によって提供されるstdio.hヘッダーファイルには、次のファイルタイプ宣言があります。
struct _iobuf{
char*_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char*_tmpfname;
};
typedef struct _iobuf FILE;
異なるCコンパイラのFILEタイプの内容は完全に同じではありませんが、類似しています。ファイルが開かれるたびに、システムはファイルの状況に応じてFILE構造の変数を自動的に作成し、情報を入力するため、ユーザーは詳細を気にする必要がありません。一般に、FILEポインターは、FILE構造の変数を維持するために使用されます。これは、より便利に使用できます。
ファイルを開いたり閉じたりする
ファイルを開く
fopen関数プロトタイプ:
FILE *fopen(const char *path, const char *mode);
パラメータ:最初のパラメータはファイルパス、2番目のパラメータはファイルを開く方法、タイプはすべて文字列です
使用例
pFile = fopen("myfile.txt", "w");
#include <stdio.h>
int main(){
FILE* pFile;
pFile = fopen("myfile.txt", "w");
if (pFile != NULL) {
fputs("fopen example", pFile);
fclose(pFile);
}
return 0;
}
そのようなファイルがない場合は、ファイルが作成されます
2番目のパラメーターの選択
ファイルの使用法 | 意味 | 指定したファイルが存在しない場合 |
---|---|---|
「R」(読む) | 読むためにファイルを開く | エラー |
「W」(書き込み) | ファイルを長さゼロに切り捨てるか、書き込み用のテキストファイルを作成します | 新しいファイルを作成する |
「Rt」(読み取り専用)1 | テキストファイルを開き、データの読み取りのみを許可する | エラー |
「Wt」(書き込み専用) | テキストファイルを開くまたは作成するためにのみ書き込み、データの書き込みのみを許可する | 新しいドキュメントを作成する |
「A」(追加) | テキストファイルの最後にデータを追加します | エラー |
「Rb」(追加) | 読み取るためにバイナリファイルを開く | エラー |
「Wb」(書き込み専用) | 書き込み用のバイナリファイルを開く | 新しいファイルを作成する |
“ab”(追加) | バイナリファイルの最後にデータを追加します | エラー |
「R +」(読み取りと書き込み) | 読み書きするには、テキストファイルを開きます | エラー |
「W +」(読み取りと書き込み) | 読み取りと書き込みを行うには、新しいファイルを作成します | 新しいドキュメントを作成する |
「A +」(読み取りと書き込み) | ファイルを開き、ファイルの最後で読み取りと書き込みを行います | 新しいファイルを作成する |
「Rb +」(読み取りおよび書き込み)2 | 読み取りと書き込み用のバイナリファイルを開きます | エラー |
「Wb +」(読み取りと書き込み) | 読み取りと書き込みを行うには、新しいバイナリファイルを作成します | 新しいファイルを作成する |
「Ab +」(読み取りと書き込み) | バイナリファイルを開き、ファイルの最後で読み取りと書き込みを行います | 新しいファイルを作成する |
ファイルを閉じる
fclose関数プロトタイプ:
int fclose(FILE *stream);
パラメータ:唯一のパラメータは、閉じる必要のあるファイルポインタです。
ファイルの読み取りと書き込み
シーケンシャル読み取りおよび書き込み
特徴 | 関数名 | に適用する |
---|---|---|
文字出力機能 | fputc | すべての出力ストリーム |
文字入力機能 | fgetc | すべての入力ストリーム |
テキスト行出力機能 | fputs | すべての出力ストリーム |
テキスト行入力機能 | fgets | すべての入力ストリーム |
フォーマットされた出力関数 | fprintf | すべての出力ストリーム |
フォーマット入力機能 | fscanf | すべての入力ストリーム |
バイナリ出力 | fwrite | ファイル |
バイナリ入力 | フレッド | ファイル |
fputc関数プロトタイプ:
int fputc( int c, FILE *stream );
パラメータ:最初のパラメータは書き込まれる文字であり、2番目のパラメータは書き込まれるファイルストリームです。
使用例
FILE* pFile = fopen("fputc.txt", "w");
char* str = "This is a test of fputc!!\n";
char* p_str = str;
while ((*p_str != '\0') && fputc(*(p_str++), stdout) != EOF);
p_str = str;
while ((*p_str != '\0') && fputc(*(p_str++), pFile) != EOF);
FILEポインタは、実際にはファイルストリームであり、これも一種のストリームであり、標準の入力および出力ストリームとほぼ同じです。
fgetc関数プロトタイプ:
int fgetc( FILE *stream );
パラメータ:streamは、読み取られる宛先ストリームです
使用例
//先使用fputs写一个文本文件
FILE* pFile = fopen("fgetc.txt", "w");
char* str = "This is a test of fgetc!!\n";
fputs("Hello world from fgetc.\n", pFile);
fclose(pFile);
//使用fgetc读取这个文本文件的内容
pFile = fopen("fgetc.txt", "r");
while(feof(pFile) == 0){
char ch = fgetc(pFile);
fputc((char)ch, stdout);
}
fclose(pFile);
fputs関数プロトタイプ:
int fputs( const char *string, FILE *stream );
パラメータ:最初のパラメータはファイルに書き込まれる文字列、2番目のパラメータは出力ストリームです
使用例
FILE* pFile = fopen("fputs.txt", "w");
char* str = "This is a test of fputs!!\n";
fputs(str, pFile);
fgets関数プロトタイプ:
char *fgets(char *restrict s, int n, FILE *restrict stream);
パラメータ:ストリームから最大n文字の文字列を読み取り、それをs文字に保存します
使用例
//先使用fputs写入一个文本文件
FILE* pFile = fopen("fgets.txt", "w");
char* str = "This is a test of fgets!!\n";
fputs(str, pFile);
fclose(pFile);
//再使用fgets读
char line[1000];
if ((pFile = fopen("fgets.txt", "r")) != NULL)
{
if (fgets(line, 1000, pFile) == NULL)
printf("fgets error\n");
else
printf("%s", line);
fclose(pFile);
}
fprintf関数プロトタイプ:
int fprintf( FILE *stream, const char *format [, argument ]...);
パラメータ:出力するストリームをストリーミングします。formatはフォーマット制御文字列、引数は複数の変数です。
使用例
int i = 10;
double fp = 1.5;
char s[] = "this is a string";
char c = '\n';
FILE* stream = fopen("fprintf.out", "w");
fprintf(stream, "%s%c", s, c);
fprintf(stream, "%d\n", i);
fprintf(stream, "%f\n", fp);
fclose(stream);
system("type fprintf.out");
printfと標準出力の違いは、最初に指定された出力ストリームパラメータが追加されることです。outサフィックスファイルの内容は、システムを使用して標準出力ストリームに直接印刷できます。
fscanf関数プロトタイプ:
int fscanf( FILE *stream, const char *format [, argument ]... );
パラメータ:形式に従ってストリームからデータを解析し、引数に順番に格納します
使用例
//先使用fprintf向文件输入
int i = 10;
double fp = 1.5;
char s[] = "string";
char c = 'U';
FILE* stream = fopen("fscanf.out", "w");
fprintf(stream, "%s %c", s, c);
//s字符串需要scanf读取的话,没有空格和换行的字符串请用空格与后面的变量隔开,如果字符串含空格,建议将字符串作为一整行用fgets读取
fprintf(stream, "%d\n", i);
fprintf(stream, "%f\n", fp);
fclose(stream);
//使用fscanf读取文件数据
stream = fopen("fscanf.out", "r");
fscanf(stream, "%s", &s);
fscanf(stream, "%c", &c); //捕捉空格
fscanf(stream, "%c", &c);
printf("%s %c\n", s, c);
fscanf(stream, "%d", &i);
fscanf(stream, "%f", &fp);
printf("%d\n%f\n", i, fp);
fclose(stream);
fwrite関数プロトタイプ:
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
パラメータ:bufferは書き込まれるデータ、sizeは要素のバイトサイズ、countは要素の数、streamは書き込まれる宛先ストリームです。
使用例
FILE* stream = fopen("fwrite.out", "w+t");
char list[] = "abcdefghijklmnopqrstuvwxyz";
if (stream != NULL) {
char numwritten = fwrite(list, sizeof(char), strlen(list), stream);
printf("Wrote %d items\n", numwritten);
fclose(stream);
}
system("type fread.out");
fwriteは、カウント文字、整数、またはサイズの文字列を書き込むことができます
fread関数プロトタイプ:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
パラメータ:バッファは読み取られるデータストレージ領域、サイズは単一要素のサイズ、カウントは
使用例
//读取上面fwrite保存的fwrite.out文件
if ((stream = fopen("fwrite.out", "r+t")) != NULL)
{
char numread = fread(list, sizeof(char), 26, stream);
printf("Number of items read = %d\n", numread);
printf("Contents of buffer = %.26s\n", list);
fclose(stream);
}
else
printf("File could not be opened\n");
ランダムな読み取りと書き込み
ファイルポインタの任意の位置にジャンプします
fseek関数プロトタイプ
int fseek(FILE * stream, long int offset, int origin);
パラメータ:streamは操作中のストリーム、offsetはオフセット、originは参照オフセットの開始位置です。
基準 | オフセット基準位置 |
---|---|
SEEK_SET | ファイルの開始 |
SEEK_CUR | ファイルポインタが指す現在の位置 |
SEEK_END | ファイルの終わり |
使用例
FILE* pFile = fopen("example.txt", "wb");
fputs("This is an apple.", pFile);
fseek(pFile, 9, SEEK_SET);
fputs(" sam", pFile);
fclose(pFile);
system("type example.txt");
開始位置を基準にしたファイルポインタのオフセットを返します
ftell関数プロトタイプ
long ftell( FILE *stream );
パラメータ:streamは、オフセットを取得するためのターゲットストリームです
使用例
FILE* stream = fopen("ftell.c", "w+");
srand(time(NULL));
int charNumber = 150;
while (charNumber--)
fputc(rand() % 57 + 65, stream);
//得到当前的偏移量
long position;
position = ftell(stream);
printf("Position after trying to read 100 bytes: %ld\n",
position);
fclose(stream);
ファイルポインタの位置がファイルの先頭に戻ります
巻き戻し関数プロトタイプ
void rewind ( FILE * stream );
パラメータ:streamは、ファイルポインタがファイルの先頭を指すターゲットストリームです。
使用例
//写一个文件用于测试
char list[100];
FILE* stream = fopen("rewind.c", "w");
srand(time(NULL));
int charNumber = 150;
while (charNumber--)
fputc(rand() % 57 + 65, stream);
fclose(stream);
stream = fopen("rewind.c", "r");
//读
fread(list, sizeof(char), 100, stream);
char position = ftell(stream);
printf("Position after read: %ld\n",
position);
//文件指针回到文件首
rewind(stream);
position = ftell(stream);
printf("Position after back to start: %ld\n",
position);
fclose(stream);
書き込みを終了し、ファイルストリームを閉じてファイルを読み取らないでください。指紋オフセットは負の数です。
FILE* stream = fopen("rewind.c", "w");
srand(time(NULL));
int charNumber = 150;
while (charNumber--)
fputc(rand() % 57 + 65, stream);
char position = ftell(stream);
printf("Position after write: %ld\n", position);
ファイルの終わりの判断
feof関数プロトタイプ
int feof( FILE *stream );
パラメータ:ファイルポインタがファイルの最後でターゲットストリームに到達するかどうかを決定します
fgetc、fgetc、fread、fprintfは、ファイルの終わりが読み取られたときにEOFを返します
使用例
//创建feof.c
FILE* stream = fopen("feof.c", "w");
srand(time(NULL));
int charNumber = 80;
while (charNumber--)
fputc(rand() % 57 + 65, stream);
fclose(stream);
//读feof.c
int count, total = 0;
char buffer[100];
if ((stream = fopen("feof.c", "r")) == NULL)
exit(1);
//结合feof就可以循环读到文件结尾
/* Cycle until end of file reached: */
while (!feof(stream))
{
/* Attempt to read in 10 bytes: */
count = fread(buffer, sizeof(char), 100, stream);
if (ferror(stream)) {
perror("Read error");
break;
}
/* Total up actual bytes read */
total += count;
}
printf("Number of bytes read = %d\n", total);
fclose(stream);
バイナリファイルの読み取り例
#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{
double a[SIZE] = { 1.0,2.0,3.0,4.0,5.0 };
double b = 0.0;
size_t ret_code = 0;
FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式
fwrite(a, sizeof(*a), SIZE, fp); // 写 double 的数组
fclose(fp);
fp = fopen("test.bin", "rb");
// 读 double 的数组
while ((ret_code = fread(&b, sizeof(double), 1, fp)) >= 1)
{
printf("%lf\n", b);
}
if (feof(fp))
printf("Error reading test.bin: unexpected end of file\n");
else if (ferror(fp)) {
perror("Error reading test.bin");
}
fclose(fp);
fp = NULL;
}