c语言中文件操作详解

目录

一、c语言中的文件

1. 为什么使用

2. 文件概念

2.1 程序文 件

2.2 数据文件

2.2.1 文本文件

2.2.2 二进制文件

3. 流的概念

3.1 流

3.2 标准流

二、c语言中文件的使用

1. 文件指针的使用(fopen和fclose)

2. 文件读写顺序

3. 读写函数介绍

3.1 fputc字符输出fputs字符串输出

3.2 fgetc字符输入fgets字符串输入

3.3 fprintf对文本输出

3.4 fscanf从文本输入

3.5 fwrite写二进制到文本

3.6 fread读取二进制文本

4. 读取完成或失败的判断

4.1 fgetc读取完的判断

4.2 fgets读取完的判断

三、文件随机读取

1. fseek指向某个位置

2. ftell判断光标与起始偏移量

3. rewind重置到起始

四、文件缓存区


一、c语言中的文件

1. 为什么使用

        文件是用来存储数据信息的,因为我们程序结束后,数据会全部消失,内存全部回收,无法寻找,这个时候就需要数据文件来存储信息(用于持久化保存)。

2. 文件概念

2.1 程序文件

        程序文件就是我们执行代码的.c文件、windows环境的.obj文件和可执行.exe文件。

2.2 数据文件(最后提一下数据文件概念)

2.2.1 文本文件

        文本文件就是通过将字符(一个字节)对应的ascll值保留到文件中,这个过程需要将字符(数字也会当成字符)转换为一个一个的ascll值,然后进行存储每个字符对应的ascll值的二进制。

2.2.2 二进制文件

        二进制文件,会将一个数据的二进制存储起来,不做任何修改

 两个文件的区别图示:

  数据文件,就是存储信息,这个数据文件的信息是可以通过程序文件进行读取和修改的,。可以通过程序文件与数据文件传输数据来保留和修改数据,最主要的就是可以保留程序运行时产生的数据。

3. 流的概念

3.1 流

        我们程序需要输出输入外部设备的内容,而每个外部设备不一样,为了方便写代码,这里引用了流的概念。可以把流当成流淌字符的河,用于流淌数据传输过去。

3.2 标准流

        一般编译器默认打开这几个标准流,stdin这个输入流stdout这个输出流,还有一个错误流stderr。这几个流类型都是FILE*这个指针类型,统称文件指针

二、c语言中文件的使用

1. 文件指针的使用(fopen和fclose)

        fopen是打开文件的函数,如果打开失败,那就会返回NULL这个空指针,而如果打开成功,那就可以进行读写等操作。格式为FILE* pf = fopen("文件名","读取方式")文件是由路径+文件主干+后缀,fopen文件名可以直接写成文件主干+后缀,表示在当前文件中寻找这个需要修改或者读取的文件名。文件路径包0括范围路径、绝对路径还有相对路径。这里绝对路径就是将整个文件名都表示出来了,把这个文件的所在地方都表示

出来了,在程序中打开文件,我们需要将/这些转义字符转换/这个普通斜杠而范围路径指的是当前文件中寻找这个文件;相对路径也是范围路径的一种,就是以当前路径作为参考物,取上一个路径或者上上个路径,这个时候就需要..来表示上个路径(首先用.来表示当前路径)

FILE* pf = fopen("C:\\Users\\bearone\\Desktop\\test.c")//绝对路径
                    \User\bearone\Desktop\test.c
FILE* pf = fopen("./test.c","r");//当前路径
FILE* pf = fopen("./../test.c","r");//上个路径
FILE* pf = fopen("./../../test.c","r");上上个路径

         fclose是用于关闭文件的函数,格式为fclose("FILE* ")一般关闭后我们需要将这个文件指针置空(空指针)

#include<stdio.h>
int main()
{
	int a = 10000;
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	else
	{
		printf("打开文件成功");
	}
	写文件
	fwrite(&a, 4, 1, pf);//以二进制输入到指针文本
	fclose(pf);
	pf = NULL;
}

2. 文件读写顺序

   

3. 读写函数介绍

写之前,我给大家展示一个图,方便好理解

3.1 fputc字符输出fputs字符串输出

        fputc用来输出字符到文本的函数,而fputs输出字符串到文本中去。格式为(int)fputc(int(字符自动转换为ascll值),文件指针),而(int成功返回非零值,失败返回NULL)fputs(const 类型*,文件指针)

fputc实例

#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	for (int i = 'a'; i <= 'z'; i++)
	{
		fputc(i, pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

fputs实例 

#include<stdio.h>
int main()
{
	char str[] = "abcdefghijklmnopqrstuvwxyz";
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs(str, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

 均输出到文本为:

3.2 fgetc字符输入fgets字符串输入

        fgetc是从文本输入字符到程序中,每一次读取都会使得光标往后移,而fgets是从文本输入字符串到程序中fgetc格式为(int)fgetc(文件指针)fgets格式char* fgets(char* str,int(读取最多字符个数),文件指针),这里fgets是指将文本中的信息输入到char* str这个指针中,这里读取的最大字符个数,如果读取最大个数小于实际中的个数那就会读取不完全,如最大读取为10,那么就会读取9个字符,如果读取最大个数大于实际中的个数,那就会读到最后一个字符就停止,最大10个,实际5个,那就会读到第6取\0(这个\0是必须加的,fgets会自动补充)fgets只会读取到一行中的字符串,如果第二行还有字符,并且还没到达最大字符个数,它也不会继续读取(注意fgetc会读取第二行)。

fgetc实例 :

#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		printf("%c", ch);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

 fgets实例:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");//打开文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char* str = malloc(27);//开辟
	if (str == NULL)
	{
		perror("malloc");
		return 1;
	}
	fgets(str, 27, pf);
	printf("%s", str);
	fclose(pf);
    free(str);
    str = NULL;
	pf = NULL;
	return 0;
}

3.3 fprintf对文本输出(扩展sprintf)

        fprintf这个用于格式化输出到流中,将程序文件打印到对应流中。格式为(int)fprintf(FILE*stream,这里printf一样)

#include<stdio.h>
struct Stu
{
	char name[20];
	char id[20];
};

int main()
{
	struct Stu s1 = { "zhansan","2403020650" };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return  1;
	}
	fprintf(pf, "name is %s\nid is %s", s1.name, s1.id);//打印到文件指针中
	fprintf(stdout, "name is %s\nid is %s", s1.name, s1.id);//打印到屏幕中(标准流)
	fclose(pf);
	pf = NULL;
	return 0;
}

 

sprintf直接输出字符串到对应的指针中。 代码实例

#include<stdio.h>
int main()
{
	char arr[30];
	int id = 24030206;
	sprintf(arr, "id = %d", id);
	printf(arr);
	return 0;
}

3.4 fscanf从文本输入(扩展sscanf)

        fscanf只不过意义变了格式化输入,格式都和scanf差不多,fscanf是向通过流输入到程序文件中fscanf(FILE*stream,和scanf使用一样)

#include<stdio.h>
struct Stu
{
	char name[20];
	char id[20];
}s1;
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fscanf(pf, "%s %s", s1.name, s1.id);//文件输入
	fscanf(stdin, "%s %s", s1.name, s1.id);//键盘输入
	printf("%s\n%s\n", s1.name, s1.id);
	fclose(pf);
	pf = NULL;
	return 0;
}

sscanf是读取指针中数据到后面的变量中去。代码实例 

#include<stdio.h>
int main()
{
	char arr[30];
	char id1[] = "2403020650";
	char id2[20];
	sprintf(arr, "id1=%s\n", id1);//右输出到左
	printf(arr);
	sscanf(arr, "%s", &id2);//左输入到右
	printf("%s\n", id2);
	return 0;
}

3.5 fwrite写二进制到文本

        fwrite二进制的形式写到文本中,也就是二进制文本。格式为fwrite(const void* ,szie_t(一个元素所占字节大小),size_t (元素个数),FILE*(流))。将指针中二进制放入流中,返回值为放入元素的个数。

#include<stdio.h>
int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	//打开文件
	FILE* pf = fopen("test.txt", "wb");//以二进制写
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	fwrite(arr, sizeof(int), 9, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

小端存储 

3.6 fread读取二进制文本

        fread就是读取二进制文件,将二进制文本读取到程序中来。格式和fwrite一模一样,fread(const void* ,size_t (一个元素占的字节大小),size_t (元素个数),FILE*(流))。返回的是读取元素个数(可以通过比较读取个数是否和自己输入个数一样来判断读取完毕)。

#include<stdio.h>
int main()
{
	int arr1[] = { 0,1,2,3,4,5,6,7,8,9 };
	//打开文件
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	fwrite(arr1, sizeof(int), 9, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	int arr2[10];
	 pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fread(arr2, sizeof(int), 9, pf);
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr2[i]);
	}
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

 

 

这些函数区别。 

4. 读取完成或失败的判断

4.1 fgetc读取完的判断

        fgetc读取成功会返回对应的ascll值,失败或者读取到文件末尾则会返回EOF

#include<stdio.h>
int main()
{
	//打开
	FILE* pf = fopen("test.txt", "w");//写
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	for (int i = 'a'; i <= 'z'; i++)
	{
		fputc(i, pf);
	}
	//关闭
	fclose(pf);
	pf = NULL;
	char ch = 0;
	//打开
	pf = fopen("test.txt", "r");//读
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	while ((ch = fgetc(pf)) != EOF)
	{
		printf("%c", ch);
	}
	printf("\n");
	if (feof(pf))
	{
		printf("读完\n");
	}
	else if (ferror(pf))
	{
		printf("错误\n");
	}
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

4.2 fgets读取完的判断

        fgets读取成功就会返回该指针的起始地址,失败或读取到文件末尾则返回NULL空指针

feof和ferror这俩个区别,feof对于读取失败错误信息,它会返回0,而对于正常读取文件结束,会返回非零。ferror就和它相反,失败就返回非零,成功读取结束返回0;

三、文件随机读取

1. fseek指向某个位置

        fseek用于定位指针指向的某个位置,意思就是可以将光标移动到某一位,格式为fseek(FILE*(流),long int offset(相对于某个位置偏移量),int origin(SEEK_SET起始位置)(SEEK_OUR当前光标)(SEEK_END文件末尾))),通过对origin使用和偏移量的使用,将光标移动到想要的位置上。

#include<stdio.h>
int main()
{
	//打开
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	char ch = 0;
	ch = fgetc(pf);
	printf("%c\n", ch);
	fseek(pf, -3, SEEK_END);
	ch = fgetc(pf);
	printf("%c\n", ch);
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

 

2. ftell判断光标与起始偏移量

        ftell用于计算此时光标与起始位置的偏移量。格式为(long int)ftell(FILE*流)。 

#include<stdio.h>
int main()
{
	//打开
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	char ch = 0;
	ch = fgetc(pf);
	printf("%c\n", ch);
	fseek(pf, -3, SEEK_END);
	ch = fgetc(pf);
	printf("%c\n", ch);
	long int r = ftell(pf);
	printf("%d\n", r);
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

 

3. rewind重置到起始

        rewind将光标重置到起始位置。格式为rewind(FILE*流)

#include<stdio.h>
int main()
{
	//打开
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//使用
	char ch = 0;
	ch = fgetc(pf);
	printf("%c\n", ch);
	fseek(pf, -3, SEEK_END);
	ch = fgetc(pf);
	printf("%c\n", ch);
	rewind(pf);
	long int r = ftell(pf);
	printf("%d\n", r);
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

四、文件缓存区

        用于提高效率

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值