6.ファイル操作

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;
}


  1. r + tに相当↩︎

  2. r + bに相当↩︎

おすすめ

転載: blog.csdn.net/qq_43808700/article/details/114106618