【C语言】文件处理函数

C语言文件操作

0. 目录

1. 文件的作用

​ 文件的意义:大家试想一下,在没有文件之前,我们所编写的C语言程序都是不具有保存功能的,这是因为程序运行时才会加载到内存,但是内存不具有记忆功能,换句话说一经断电关机内存中存储的数据就会全部丢失,这个时候我们想要保存数据,就要使用如硬盘、磁盘等存储设备。

​ 在举一个编程的例子,我们已经实现了一个学生成绩管理系统,当我们已经录入学生信息完毕后,我们终止程序运行,但是当下一次重新运行程序的时候,之前录入的数据就会全部丢失!所以我们想要使用保存数据的功能,使用文件就是一种保存数据的解决方案,也就是说文件就是用来实现数据持久化的。

2. 什么是文件

2.1 程序文件与数据文件

在程序设计语言中所谈论的文件主要分为以下两大类:程序文件数据文件

  1. 程序文件:例如说C语言所编写的源代码文件在经过编译链接之后会生成后缀名为.obj的目标文件和后缀名为.exe的可执行文件
  2. 数据文件:是指程序运行时所需的文件,例如在程序运行中想要从文件中读出相应数据,或者将一些数据写入某个文件中

2.2 文件名

文件名:一个文件用以区别于别的文件的唯一标识,也称作文件名

文件名的组成:通常由三部分构成——文件路径文件名主干文件后缀

例如:c:\code\test.txt

注意:文件名可以不包括文件后缀,例如单纯一个c:\code\test的文本文件

3. 文件的打开与关闭

3. 1 文件指针

文件信息区:在C语言中,每个所正在使用的文件都会在内存中开辟相应的文件信息区,用来存放关于文件的信息(如文件名、文件大小、文件状态)这些信息被保存在一个结构体变量当中,该结构体类型由系统进行声明与定义、取名为FILE

例如在VS2013编译环境中stdio.h的头文件中就有以下FILE类型的定义

struct _iobuf {
    char *_ptr;
    int  _cnt;
    char *_base;
    int  _flag;
    int  _file;
    int  _charbuf;
    int  _bufsiz;
    char *_tmpfname;
   };
typedef struct _iobuf FILE;

在使用文件的过程中,通常会使用一个FILE*类型的指针变量来维护这个结构体变量。下面我们可以创建一个FILE*类型的指针变量

FILE* pf; // 文件指针变量

通过pf指针变量,我们就可以让pf指针指向一个文件信息区,通过这个pf指针进一步找到与之相关联的文件

3.2 文件的打开与关闭

3.2.1 文件打开与关闭函数介绍

C语言提供了一个打开文件的函数:fopen

网站链接:https://legacy.cplusplus.com/reference/cstdio/fopen/?kw=fopen

语法格式:FILE* fopen(const char* filename, const char* mode)

函数作用:通过mode指定的方式,打开一个文件名为filename的文件,并返回一个与之相关联的文件类型指针

下面是文件常见的一些打开方式(mode):

文件打开方式含义如果文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件报错
“w”(只写)为了输出数据,打开一个文本文件创建一个文件
“a”(追加)向文本文件末尾追加文本数据创建一个文件
“rb”(只读)为了输入数据,打开一个已经存在的二进制文件报错
“wb”(只写)为了输出数据,打开一个二进制文件创建一个文件
“ab”(追加)向一个二进制文件末尾追加数据创建一个文件
“r+”(读写)为了读写数据,打开一个已经存在的文本文件报错
“w+”(读写)为了读写数据,打开一个文本文件创建一个文件
“a+”(读写)打开一个文本文件,在文件尾读写数据创建一个文件
“rb+”(读写)为了读写数据,打开一个已经存在的二进制文件报错
“wb+”(读写)为了读写数据,打开一个二进制文件创建一个文件
“ab+”(读写)打开一个二进制文件,在末尾读写数据创建一个文件

C语言还提供了一个关闭文件的函数:fclose

网站链接:https://legacy.cplusplus.com/reference/cstdio/fclose/?kw=fclose

语法格式:int fclose(FILE* stream)

函数作用:关闭文件流对象stream

3.2.2 文件打开与关闭演示
int main() {
    // 打开文件
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL) {
        perror("fopen");
        return -1;
    }
    // 文件操作
    // 关闭文件
    fclose(pf);
    return 0;
}

4. 文件的顺序读写

4.1 fgetc与fputc函数

4.1.1 函数使用介绍

C语言提供了一个字符输出函数:fputc

网站链接:https://legacy.cplusplus.com/reference/cstdio/fputc/?kw=fputc

语法格式:int fputc(int character, FILE* stream)

函数作用:将字符character写入文件流对象stream中,如果成功,返回写入字符,如果写入失败,返回EOF

C语言也提供了对应的字符读入函数:fgetc

网站链接:https://legacy.cplusplus.com/reference/cstdio/fgetc/?kw=fgetc

语法格式:int fgetc(FILE* stream)

函数作用:返回文件流对象中当前所指向的字符,如果成功读取返回相应字符,读取失败或读取完毕返回EOF

4.1.2 函数使用演示

写入文件:

// 写入文件
int main() {
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	// 使用文件
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	// 关闭文件
	fclose(pf);
	return 0;
}

读取文件:

// 读取文件
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	// 使用文件
	char ch;
	while ((ch = fgetc(pf)) != EOF) {
		printf("%c ", ch);
	}
	// 关闭文件
	fclose(pf);
	return 0;
}

4.2 fgets与fputs函数

4.2.1 函数使用介绍

C语言不仅有针对单个字符进行读写的函数,还提供了一个文本行输出函数:fputs

网站链接:https://legacy.cplusplus.com/reference/cstdio/fputs/?kw=fputs

语法格式:int fputs(const char* str, FILE* stream)

函数作用:将str所指向的字符串写入文件流对象stream中,如果成功返回非负值,若失败返回EOF

同样C语言也提供了与之配套的文本行读取函数,可读取多个字符:fgets

网站链接:https://legacy.cplusplus.com/reference/cstdio/fgets/?kw=fgets

语法格式:char* fgets(char* str, int num, FILE* stream)

函数作用:读取文件流对象当中的多个字符,但是最多读取num-1个字符,如果期间读取到文件结束标志符或者一行文本读取完毕则结束读取,将读取结果写入str指向的内存空间中,并追加\0,如果正常读取则返回str,如果读取过程中发生了错误或者没有一个字符可以读取则返回空指针NULL

4.2.2 函数使用演示

写入文件

// fputs使用
int main() {
	// 打开文件
	FILE* pf = fopen("fputs.txt", "w");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	int ret = fputs("hello world!", pf);
	printf("%d\n", ret);
	// 关闭文件
	fclose(pf);
	return 0;
}

读取文件

// fgets使用
int main() {
	// 打开文件
	FILE* pf = fopen("fputs.txt", "r");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	char str[20] = { 0 };
	char* ret = fgets(str, 19, pf);
	printf("%s\n", ret);
	// 关闭文件
	fclose(pf);
	return 0;
}

4.3 fscanf与fprintf函数

4.3.1 函数使用介绍

C语言提供了一个格式化输出函数:fprintf

网站链接:https://legacy.cplusplus.com/reference/cstdio/fprintf/?kw=fprintf

语法格式:int fprintf(FILE* stream, const char* format, ...)

函数作用:将format指向的格式化数据写入文件流对象stream中,如果写入成功返回写入字符,反之返回负数

C语言也提供了与之相配套的格式化读取函数:fscanf

网站链接:https://legacy.cplusplus.com/reference/cstdio/fscanf/?kw=fscanf

语法格式:int fscanf(FILE* stream, const char* stream, ...)

函数作用:将文件流对象stream中读取格式化数据存储到format指向对象中

4.3.2 函数使用演示

写入文件

typedef struct S {
	char name[10];
	int age;
}S;
// fprintf使用
int main() {
	// 打开文件
	FILE* pf = fopen("fprintf.txt", "w");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	S s = {"rice", 20};
	// 使用文件
	int ret = fprintf(pf, "%s %d", s.name, s.age);
	printf("%d\n", ret);
	// 关闭文件
	fclose(pf);
	return 0;
}

读取文件

typedef struct S {
	char name[10];
	int age;
}S;
// fscanf使用
int main() {
	// 打开文件
	FILE* pf = fopen("fprintf.txt", "r");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	S s = { 0 };
	int ret = fscanf(pf, "%s %d", s.name, &s.age);
	printf("%d\n", ret);
	printf("%s %d\n", s.name, s.age);
	// 关闭文件
	fclose(pf);
	return 0;
}

4.4 fread与fwrite函数

注:上述的函数都是适用于所有输入流和输出流的,即也是可以从控制台读取和输出到控制台上的,但是这组函数只适用于文件流对象,并且下面要介绍的这一对函数是针对二进制文件的。

4.4.1 函数使用介绍

C语言提供了一个二进制输出函数:fwrite

网站链接:https://legacy.cplusplus.com/reference/cstdio/fwrite/?kw=fwrite

语法格式:size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream)

函数作用:会将ptr指向空间内容count * size个字节转化为二进制写入文件流对象stream中

同样的C语言也提供了与之相配套的二进制读取函数:fread

网站链接:https://legacy.cplusplus.com/reference/cstdio/fread/?kw=fread

语法格式:size_t fread(void* ptr, size_t size, size_t count, FILE* stream)

函数作用:会将文件流对象中读取count* size个字节对应的二进制信息读取存入ptr指向的空间中

4.4.2 函数使用演示

写入文件

typedef struct S {
	char name[10];
	int age;
}S;
// fwrite使用
int main() {
	// 打开文件
	FILE* pf = fopen("fwrite.txt", "wb");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	S s = { "rice", 20 };
	int ret = fwrite(&s, sizeof(S), 1, pf);
	printf("%d\n", ret);
	// 关闭文件
	fclose(pf);
	return 0;
}

读取文件

typedef struct S {
	char name[10];
	int age;
}S;

// fread使用
int main() {
	// 打开文件
	FILE* pf = fopen("fwrite.txt", "rb");
	if (pf == NULL) {
		perror("fopen");
		return -1;
	}
	S s = { 0 };
	int ret = fread(&s, sizeof(S), 1, pf);
	printf("%d\n", ret);
	printf("%s %d\n", s.name, s.age);
	// 关闭文件
	fclose(pf);
	return 0;
}

5. 文件的随机读写

5.1 fseek函数

网站链接:https://legacy.cplusplus.com/reference/cstdio/fseek/?kw=fseek

语法格式:int fseek(FILE* stream, long int offset, int origin)

函数作用:可以根据originoffset参数设置重新变更文件指针的位置

origin含义
SEEK_SET文件起始位置
SEEK_CUR文件指针当前位置
SEEK_END文件末尾位置

下面是fseek函数使用演示

int main() {
	// 打开文件
	FILE* pfWrite = fopen("fseek.txt", "w");
	if (pfWrite == NULL) {
		perror("fopen pfWrite");
		return -1;
	}
	fputs("hello world!", pfWrite);
	// 关闭文件
	fclose(pfWrite);
	// 打开文件
	FILE* pfRead = fopen("fseek.txt", "r");
	if (pfRead == NULL) {
		perror("fopen pfRead");
		return -1;
	}
	// 文件指针起始位置偏移一位
	fseek(pfRead, 1, SEEK_SET);
	char ch1 = fgetc(pfRead);
	printf("%c\n", ch1);
	// 文件指针当前位置偏移一位
	fseek(pfRead, 1, SEEK_CUR);
	ch1 = fgetc(pfRead);
	printf("%c\n", ch1);
	// 文件指针距离末尾偏移-1位
	fseek(pfRead, -1, SEEK_END);
	ch1 = fgetc(pfRead);
	printf("%c\n", ch1);
	// 关闭文件
	fclose(pfRead);
	return 0;
}

5.2 ftell函数

C语言提供了一个可以计算文件指针当前位置距离文件起始位置的偏移量函数:ftell

网站链接:https://legacy.cplusplus.com/reference/cstdio/ftell/?kw=ftell

语法格式:long int ftell(FILE* stream)

函数作用:返回文件指针当前位置与文件起始位置的偏移量

下面是ftell函数的使用演示:

// ftell使用
int main() {
	// 打开文件
	FILE* pfWrite = fopen("ftell.txt", "w");
	if (pfWrite == NULL) {
		perror("pfWrite fopen");
		return -1;
	}
	fputs("hello world!", pfWrite);
	// 关闭文件
	fclose(pfWrite);
	// 打开文件
	FILE* pfRead = fopen("ftell.txt", "r");
	if (pfRead == NULL) {
		perror("pfRead fopen");
		return -1;
	}
	char ch = fgetc(pfRead);
	ch = fgetc(pfRead);
	ch = fgetc(pfRead);
	ch = fgetc(pfRead);
	// 计算当前偏移量
	int offset = ftell(pfRead);
	printf("当前偏移量为: %d\n", offset);
	// 关闭文件
	fclose(pfRead);
	return 0;
}

5.3 rewind函数

C语言还提供了可以让文件指针重新回到文件起始位置函数:rewind

网站链接:https://legacy.cplusplus.com/reference/cstdio/rewind/?kw=rewind

语法格式:void rewind(FILE* stream)

函数作用:让文件指针重新回到文件起始位置

下面是rewind函数的使用演示

// rewind函数使用
int main() {
	// 打开文件
	FILE* pfWrite = fopen("rewind.txt", "w");
	if (pfWrite == NULL) {
		perror("pfWrite fopen");
		return -1;
	}
	fputs("hello world!", pfWrite);
	// 关闭文件
	fclose(pfWrite);
	// 打开文件
	FILE* pfRead = fopen("rewind.txt", "r");
	if (pfRead == NULL) {
		perror("pfRead fopen");
		return -1;
	}
	fseek(pfRead, 2, SEEK_SET);
	// 计算当前偏移量
	int offset = ftell(pfRead);
	printf("当前偏移量为%d\n", offset);
	// 使用rewind函数
	rewind(pfRead);
	// 重新计算偏移量
	offset = ftell(pfRead);
	printf("当前偏移量为%d\n", offset);
	// 关闭文件
	fclose(pfRead);
	return 0;
}

6. 文件读取结束的判定

6.1 文件读取结束的判定

注意:文件读取过程中,不要依靠feof函数的返回值来判断文件是否读取结束

feof函数的作用是:当文件读取结束的时候判断结束的原因是否是因为遇到文件尾

  • 文本文件判断是否读取结束,需要通过fgetc或者fgets函数的返回值进行判断

    1. fgetc函数如果返回值为EOF,说明文件读取结束
    2. fgets函数如果返回值为NULL,说明文件读取结束
  • 二进制文件判断是否读取结束,需要通过返回值的个数是否小于实际应该读取的个数

    1. 如果fread函数返回值小于实际需要读取的个数则说明文件读取结束
6.2 文件读取结束判定演示

对文本文件读取结束进行判断:

// 文本文件判断文件是否读取结束
int main() {
	// 打开文件
	FILE* pfWrite = fopen("TextEndOfFile.txt", "w");
	if (pfWrite == NULL) {
		perror("pfWrite fopen");
		return -1;
	}
	fputs("hello world!", pfWrite);
	// 关闭文件
	fclose(pfWrite);
	// 打开文件
	FILE* pfRead = fopen("TextEndOfFile.txt", "r");
	if (pfRead == NULL) {
		perror("pfRead fopen");
		return -1;
	}
	char ch = 0;
	while ((ch = fgetc(pfRead)) != EOF) {
		putchar(ch);
	}
	// 当文件读取结束后,使用feof函数判断是否是读取到末尾
	if (feof(pfRead)) {
		printf("文件正常读取到末尾!\n");
	} else {
		printf("文件异常读取结束!\n");
	}
	// 关闭文件
	fclose(pfRead);
}

对二进制文件读取结束进行判断

// 二进制文件判断是否读取结束
typedef struct S {
	char name[10];
	int age;
}S;
int main() {
	// 打开文件
	FILE* pfWrite = fopen("BinEndOfFile.txt", "wb");
	if (pfWrite == NULL) {
		perror("pfWrite fopen");
		return -1;
	}
	S s1 = { "rice",  20};
	S s2 = { "json", 21 };
	S stus[2] = { s1, s2 }; // 创建一个结构体数组
	fwrite(stus, sizeof(S), 2, pfWrite);
	// 关闭文件
	fclose(pfWrite);
	// 打开文件
	FILE* pfRead = fopen("BinEndOfFile.txt", "rb");
	if (pfRead == NULL) {
		perror("pfRead fopen");
		return -1;
	}
	int sz = sizeof(stus) / sizeof(stus[0]);
	if (fread(stus, sizeof(S), 2, pfRead) == sz) {
		printf("文件读取完毕\n");
	}
	// 关闭文件
	fclose(pfRead);
	return 0;
}
  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
C语言文件操作及函数大全 2.文件操作函数: (1)文件打开函数fopen fopen函数用来打开一个文件,其调用的一般形式为: 文件指针名=fopen("文件名","使用文件方式"); 其中,“文件指针名”必须是被说明为FILE 类型的指针变量,“文件名”是被打开文件文件名。 “使用文件方式”是指文件的类型和操作要求。“文件名”是字符串常量或字符串数组。例如: FILE *fp; fp=fopen("file b","r"); 其意义是在当前目录下打开文件file b, 只允许进行“读”操作,并使fp指向该文件。 又如: FILE *fp fp=("c:\\file_a',"rb") 其意义是打开C驱动器磁盘的根目录下的文件file_a, 这是一个二进制文件,只允许按二进制方式进行读操作。两个反斜线“\\ ”中的第一个表示转义字符,第二个表示根目录。"\\"对于打开磁盘下的文件,要注意两个双斜线的正确应用,在表示绝对路径时,每一级目录都要用"\\", 例如:fp=fopen("d:\\study\\file_b","r+"); ####使用文件的方式共有12种,下面给出了它们的符号和意义。 文件使用方式 意 义 “rt” 只读打开一个文本文件,只允许读数据 “wt” 只写打开或建立一个文本文件,只允许写数据 “at” 追加打开一个文本文件,并在文件末尾写数据 “rb” 只读打开一个二进制文件,只允许读数据 “wb” 只写打开或建立一个二进制文件,只允许写数据 “ab” 追加打开一个二进制文件,并在文件末尾写数据 “rt+” 读写打开一个文本文件,允许读和写 “wt+” 读写打开或建立一个文本文件,允许读写 “at+” 读写打开一个文本文件,允许读,或在文件末追加数据 “rb+” 读写打开一个二进制文件,允许读和写 “wb+” 读写打开或建立一个二进制文件,允许读和写 “ab+” 读写打开一个二进制文件,允许读,或在文件末追加数据 对于文件使用方式有以下几点说明:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值