【C】文件操作

目录

一、文件的分类

二、文件的打开与关闭

三、文件的使用方式

四、流

五、读写文件

六、文件指针

七、文件内数据存储类型

八、判断文件读取失败的原因

九、文件缓冲区


使用文件可以将程序的数据进行存储。

一、文件的分类

程序文件

包括源文件(.c)、目标文件(.obj)、可执行程序(.exe)

数据文件

程序运行时输入、输出数据的文件

二、文件的打开与关闭

 打开一个文件时,内存中会开辟空间将该文件的信息存放在一个结构体变量中,该结构体名为 FILE。

fopen

打开一个文件,返回指向该文件结构体变量的指针,打开失败则返回空指针。

 当文件在该程序目录下可使用文件名打开该文件,否则要使用该文件的绝对路径。当以绝对路径打开文件时,须对路径中的每个「\」进行转义。

fclose

关闭文件的函数,文件关闭成功则返回 0,关闭失败则返回 EOF。

 perror

打印程序当前错误信息的函数

例:

FILE* f = NULL;//接收函数返回值的指针
f = fopen("test.txt", "r");//打开文件进行「只读」操作
//或 f = fopen("C:\\Users\\a\\Desktop\\test\\test.txt", "r");(绝对路径)
if (f == NULL)//判断是否打开失败
{
	perror("");//打印错误信息
	return;//结束程序
}
fclose(f);//关闭文件

三、文件的使用方式

 

包含「写」功能打开文件时,会清空文件内原有内容。

使用「读写」时,若想切换文件使用方式(例:「读」完后要进行「写」),都需要使用 fflush 刷新文件缓冲区,将未传输完的数据进行传输,才能进行正常「读」或「写」。

四、流

 可输入、输出数据的数据类型,FILE 类型的变量就叫做流

当使用 fopen 打开文件时,其实是将文件转换为流,从而使它可以输入、输出数据。

当程序运行时,会打开三个流:stdin —— 标准输入流(键盘)、stdout —— 标准输出流(屏幕)、stderr —— 标准错误流(屏幕)

stdio.h 表示 standard input(标准输入流)、standard output(标准输出流),这就是为什么我们在使用输入、输出函数时(如: scanf(输入)、printf(输出))的时候需要包含 <stdio.h>

既然流是由文件转换而来的,那也就是说我们可以对屏幕所对应的 stdout 进行输出操作,效果和 printf 一样。

fputs("hello world", stdout);//将字符串输出到stdout

五、读写文件

 所有读写文件函数都需包含 <stdio.h>

「f」 系列的输入输出函数都作用于所有流

「输入」、「输出」都是以内存为准,比如要往文件内写数据,那就是从内存输出数据到文件,所以叫输出流;读文件时,就是将文件内数据输入到内存中,所以叫输入流。

 fputc

  执行成功则返回输出的字符 ASCII 码值,失败则返回 EOF

FILE* pf = fopen("test.txt", "w");//打开文件进行「只写」操作
if (pf == NULL)
{
	perror("");
	return;
}
fputc('a', pf);//将字符a从内存输出到文件内
//或 fputc(97,pf)//ASCII码值
fclose(pf);

 

  fgetc

执行成功则返回输入的字符 ASCII 码值,失败则返回 EOF

 

char c = "";//接收读到的数据
FILE* pf = fopen("test.txt", "r");//打开文件并进行「只读」操作
if (pf == NULL)
{
	perror("");
	return;
}
c = fgetc(pf);//将读取到的数据放入c
printf("%c", c);//打印
fclose(pf);

 fputs

执行成功则返回一个非负数,执行失败则返回 EOF

FILE* pf = fopen("test.txt", "w");//打开文件进行「只写」操作
if (pf == NULL)
{
	perror("");
	return;
}
fputs("hello world", pf);//将字符串从内存输出到文件内
fclose(pf);

 

 fgets

执行成功则返回存放字符串的变量,执行失败则返回 NULL

char s[15] = { 0 };//存放读取到字符串的变量
	FILE* pf = fopen("test.txt", "r");//打开文件进行「只读」操作
	if (pf == NULL)
	{
		perror("");
		return;
	}
	fgets(s,15,pf);//将字符串从内存输出到文件内
	printf(s);
	fclose(pf);

 

 fprintf

执行成功则返回输出的字节数,执行失败则返回负数

int a = 1;
char s[5] = "abc";

FILE* pf = fopen("test.txt", "w");//打开文件进行「只写」操作
if (pf == NULL)
{
	perror("");
	return;
}
fprintf(pf, "%d %s", a, s);//将a、s以对应格式从内存输出到文件
fclose(pf);

return 0;

fscanf

执行成功返回成功转换和分配的字段的数量(不包括已读取但未分配的字段)。若执行失败,则返回 EOF

 

int a = 0;//存放读取到数据的变量
char s[5] = "";//存放读取到数据的变量

FILE* pf = fopen("test.txt", "r");//打开文件进行「只读」操作
if (pf == NULL)
{
	perror("");
	return;
}
fscanf(pf, "%d %s", &a, s);//以空格分隔,将读取到的数据以对应数据类型放入a、s变量中
printf("%d %s", a, s);//打印
fclose(pf);

sprintf

将数据以字符串形式输出

返回当前存储在缓冲区内数据的字节数

int n = 1;
char s[3] = "";//存放读取数据的变量

sprintf(s, "%d", n);//将n中的数据转为字符串输出到s中
printf(s);//以字符串形式打印

sscanf

将字符串转换为对应格式输入

返回成功转换和分配的字段数量,若出现错误则返回 EOF

int n = 0;//存放读取数据的变量
char s[3] = "18";

sscanf(s, "%d", &n);//将s中的数据转为整型输出到n中
printf("%d", n);//以整型形式打印

 fwrite

将一条数据以二进制输出到流,返回实际输出的完整条目数量

int arr[3] = { 1,2,3 };

FILE* pf = fopen("test.txt", "w");//打开文件进行「只写」操作
if (pf == NULL)
{
	perror("");
	return;
}
fwrite(arr, sizeof(arr), 1, pf);//将arr从内存以二进制输出到文件
fclose(pf);

fread

将一条数据以二进制输入,返回实际输出的完整条目数量

int arr[3] = { 0 };//存放读取到数据的变量

FILE* pf = fopen("test.txt", "r");//打开文件进行「只读」操作
if (pf == NULL)
{
	perror("");
	return;
}
fread(arr, sizeof(arr), 1, pf);//在pf指向的流中读取1次sizeof(arr)字节的数据放入arr
printf("%d %d %d", arr[0], arr[1], arr[2]);//打印
fclose(pf);

六、文件指针

 文件指针指向改文件正「读」或「写」到的位置。

fseek

调整文件指针的指向

执行成功返回 0,执行失败返回非 0 值

char c = "";//存放读取到数据的变量
FILE* pf = fopen("test.txt", "r");//打开文件进行「只读」操作
if (pf == NULL)
{
	perror("");
	return;
}
fseek(pf, 1, SEEK_SET);//将文件指针指向起始位置+1
c = fgetc(pf);
printf("%c", c);
fclose(pf);

 

ftell

获取文件指针当前指向位置相对于起始位置的偏移量

long n = 0;//接收返回值的变量(返回值类型为long)
FILE* pf = fopen("test.txt", "r");//打开文件进行「只读」操作
if (pf == NULL)
{
	perror("");
	return;
}
fseek(pf, 3, SEEK_SET);//将文件指针指向起始位置+3
n = ftell(pf);//获取文件位置
printf("%ld", n);//打印文件位置
fclose(pf);

rewind

 将文件指针指向起始位置

long n = 0;//接收返回值的变量(返回值类型为long)
FILE* pf = fopen("test.txt", "r");//打开文件进行「只读」操作
if (pf == NULL)
{
	perror("");
	return;
}
fseek(pf, 3, SEEK_SET);//将文件指针指向起始位置+3
rewind(pf);//将文件指针指向起始位置
ftell(pf);//获取文件指针当前指向位置
printf("%ld", n);//打印文件位置
fclose(pf);

七、文件内数据存储类型

 根据数据在文件内的存储类型可以将文件分为「文本文件」和「二进制文件」

文本文件

文件内数据以 ASCII 码值存储

  二进制文件

文件内数据以二进制存储

八、判断文件读取失败的原因

 文件读取失败的原因分为两种:遇到结尾、遇到错误

feof

若当前文件指针指向文件尾,说明已读完文件,返回非 0 值,否则返回 0

ferror

若当前文件指针指向文件位置发送错误,返回非 0 值,否则返回 0

例:

FILE* p = fopen("test.txt", "w+");//打开文件
char a[] = "abc";
char b[10];//存放读取数据的变量
int count = 0;//记录读取文件次数的变量
fwrite(a, 1, 4, p);//将a中的数据写入文件
fflush(p);//刷新文件缓冲区以开始读取数据
count = fread(b, 1, 5, p);//将文件内的数据读5次,每次读1字节,fread返回有效读写数据条目
count = fread(b, 1, 1, p);//这时文件已经读完了,再次进行读写
if (count != 4)//若读取到字符个数与文件中字符个数不相等
{
	if (feof(p))
		printf("文件已读完\n");
	else if (ferror(p))
		printf("读取出现错误\n");
}
fclose(p);//关闭文件

九、文件缓冲区

每一个打开的文件在内存中都会有一个文件缓冲区,用于存放输出的数据,只有当缓冲区满了,或刷新缓冲区,才会将数据进行传输,用于提高系统的工作效率,防止传输数据次数过多导致其他功能效率变低。缓冲区大小由编译器决定。

例:测试文件缓冲区

FILE* p = fopen("test.txt", "w");
fputc("a", p);//将a写入p
printf("已将数据写入缓冲区,此时文件中并无数据\n");
printf("休眠中...\n");
Sleep(10000);//休眠10秒
fflush(p);
printf("已刷新缓冲区,此时可在文件中查看到数据\n");
printf("休眠中...\n");
Sleep(10000);//休眠10秒
fputc("b", p);//将a写入p
printf("已再次追加数据到文件中,此时在文件中查看不到该数据\n");
printf("休眠中...\n");
Sleep(10000);
fclose(p);//关闭文件
printf("已将文件关闭,此时可在文件中查看到追加数据\n");
printf("休眠中...");
Sleep(10000);
p = NULL;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值