完全自学C(干货) —— 文件

目录

一,文件分类

程序文件

数据文件

 二,文件

文件名

文件指针

文件的打开和关闭

文件的顺序读写

文件的随机读写

文本文件和二进制文件

文件的结束判定

文件缓冲区

案例


  • 程序文件
  • 数据文件

一,文件分类

程序文件

  • 源程序文件(.c);
  • 目标文件(windows环境.obj),编译过程中的临时文件;
  • 可执行文件(windows环境.exe)等;

完全自学C(干货) —— 文件_第1张图片

数据文件

  • 文件的内容不一定是程序,而是程序运行时读写的数据;
  • 如程序运行需要从中读取数据的文件,或输出内容的文件;

 二,文件

  • 一个文件要有一个唯一的文件标识,以便用户识别和引用;

文件名

  • 文件路径
  • 文件名主干
  • 文件后缀

如c:\code\test.txt

文件指针

  • 缓冲文件系统中,关键的概念是“文件类型指针”,简称文件指针;
  • 每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等);
  • 这些信息是保存在一个结构体变量中的,该结构体类型系统有声明,取名FILE;
  • 不同C编译器,FILE类型包含的内容不完全相同,但大同小异;
  • 每当打开一个文件时,系统会根据文件情况,自动创建一个FILE结构的变量,并填充其中的信息;
  • 一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便;
  • 如 FILE* pf;

完全自学C(干货) —— 文件_第2张图片

文件的打开和关闭

  • 文件在读写之前,应该先打开文件,在使用结束后,应该关闭文件;
  • 打开文件的同时,都会返回一个FILE*的指针变量指向该文件;
  • 打开文件fopen,关闭文件fclose;
int main()
{
	FILE* pf = fopen("F:\\VS\\Project1\\test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}

	fclose(pf);
	pf = NULL;
	return 1;
}

注:文件使用方式

完全自学C(干货) —— 文件_第3张图片

文件的顺序读写

//输入、输出当个字符
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//输出/写入字符
	fputc('b', pf);
	fputc('i', pf);
	fputc('t', pf);
	//文件指针移动到起始位置
	fseek(pf, 0L, SEEK_SET);
	//输入/读取字符
	printf("%c", fgetc(pf));
	printf("%c", fgetc(pf));
	printf("%c", fgetc(pf));

	fclose(pf);
	pf = NULL;
	return 1;
}
//输入、输出一行字符
int main()
{
	char str[] = "abcde";
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//输出/写入字符串
	fputs("bit", pf);
	//文件指针移动到起始位置
	fseek(pf, 0L, SEEK_SET);
	//输入/读取字符串
	fgets(str, 2, pf); //2个字符包含'\0'
	printf("%s", str);
	fgets(str, 2, pf); //2个字符包含'\0'
	printf("%s", str);

	fclose(pf);
	pf = NULL;
	return 1;
}
//格式化数据输入、输出
struct S
{
	char str[100];
	int num;
};

int main()
{
	struct S s1 = { "bit",10 };
	struct S s2 = { {0},0 };
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//输出/写入格式化数据
	fprintf(pf, "%s ", s1.str);
	fprintf(pf, "%d ", s1.num);
	//文件指针移动到起始位置
	fseek(pf, 0L, SEEK_SET);
	//输入/读取格式化数据,截止到空格
	fscanf(pf, "%s", s2.str);
	fscanf(pf, "%d", &(s2.num));
	printf("%s %d", s2.str, s2.num);

	fclose(pf);
	pf = NULL;
	return 1;
}
//二进制输入、输出
struct S
{
	char str[100];
	int num;
};

int main()
{
	struct S s1 = { "bit",10 };
	struct S s2 = { {0},0 };
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//二进制输出/写入
	fwrite(&s1,sizeof(struct S),1,pf);
	//文件指针移动到起始位置
	fseek(pf, 0L, SEEK_SET);
	//二进制输入/读取
	fread(&s2, sizeof(struct S), 1, pf);
	printf("%s %d", s2.str, s2.num);

	fclose(pf);
	pf = NULL;
	return 1;
}

内存与硬盘读写: 

 完全自学C(干货) —— 文件_第4张图片

注:文件读写函数
完全自学C(干货) —— 文件_第5张图片

流概率:

  • 文件流;
  • 标准输入输出流stdin/stdout;

标准输入输出流读写

  • gets,获取一行字符串从stdio;
  • puts,写出一行字符串到stdout;

备注:

  • scanf/printf,针对标准输入输出流,格式化输入输出语句;
  • fscanf/fprintf,针对所有输入输出流,格式化输入输出语句;
  • sscanf/sprintf,sscanf是从字符串中读取格式化的数据,sprintf是把格式化数据输出到字符串;
struct S
{
	char name[10];
	int num;
	float score;
};

int main()
{
	struct S s1 = { "lisi",20,99.5f };
	char str[100] = { 0 };
	//从s1中格式化数据,输出到str
	sprintf(str, "%s %d %f", s1.name, s1.num, s1.score);
	printf("%s\n", str);

	struct S s2 = { 0 };
	//从str中读取格式化数据,到s2
	sscanf(str, "%s %d %f", s2.name, &(s2.num), &(s2.score));
	printf("%s %d %f", s2.name, s2.num, s2.score);
	return 0;
}

文件的随机读写

  • fseek,根据文件指针的位置和偏移量来定位文件指针;
  • origin,需为SEEK_CUR(当前位置)、SEEK_END(文件末尾位置)、SEEK_SET(文件起始位置);
  • ftell返回文件指针相对于起始位置的偏移量;
  • rewind,让文件指针的位置回到文件的起始位置;
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//输出/写入字符
	fputc('b', pf);
	fputc('i', pf);
	fputc('t', pf);
	//文件指针移动到起始位置
	fseek(pf, 0L, SEEK_SET);
	printf("%c\n", fgetc(pf));
	//文件指针移动到末尾位置
	fseek(pf, -2L, SEEK_END);
	printf("%c\n", fgetc(pf));
	//文件指针移动到当前位置
	fseek(pf, 0L, SEEK_CUR);
	printf("%c\n", fgetc(pf));
	//返回当前指针偏移量
	printf("%d\n", ftell(pf));
	//文件指针移动到起始位置
	rewind(pf);
	printf("%c\n", fgetc(pf));

	fclose(pf);
	pf = NULL;
	return 1;
}

文本文件和二进制文件

  • 更加数据的组织形式分类为文本文件和二进制文件;
  • 数据在内存中以二进制形式存储,不加转换即输出到外存的,即为二进制文件;
  • 数据在内存中以二进制形式存储,转换为ASCII码输出到外存的,即为文本文件;

数据在文件中存储形式

  • 字符一律以ASCII码形式存储;
  • 数值型数据,即可ASCII码形式存储,也可二进制形式存储;

完全自学C(干货) —— 文件_第6张图片

文件的结束判定

feof
  • 常被错误使用,用来判定文件结束;
  • 在文件读取过程中,不能用feof函数的返回值,直接用来判断文件是否结束;
  • 而是应该用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束;

文本文件读取是否结束

  • fgetc,读取结束时返回EOF,正常读取为字符ASCII码值;
  • fgets,读取结束时返回NULL,正常读取为字符串起始位置;

二进制文件读取是否结束

  • fread,正常返回实际元素个数,如小于实际要读的个数则文件读取结束了;
//将文件test1.txt,复制到test2.txt
int main()
{
	FILE* pfr = fopen("test1.txt", "r");
	if (pfr == NULL)
	{
		perror("pfr");
		return 0;
	}
	FILE* pfw = fopen("test2.txt", "w");
	if (pfw == NULL)
	{
		perror("pfw");
		return 0;
	}

	char c = 0;
	//读取失败或文件结束时,均会返回EOF
	while ((c = fgetc(pfr)) != EOF)
	{
		fputc(c, pfw);
	}

	if (ferror(pfr))
		puts("I/0,error when reading!");
	else if (feof(pfr))
		puts("End of File!");

	fclose(pfr);
	pfr = NULL;
	fclose(pfw);
	pfw = NULL;
	return 1;
}

文件缓冲区

  • ANSIC标准采用“缓冲文件系统”处理数据文件的;
  • 缓冲文件系统,是指系统自动地在内存中为程序中每个正在使用的文件开辟一块“文件缓冲区”;
  • 从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上;
  • 从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区,充满缓冲区后在逐个地将数据送到程序数据区;
  • 缓冲区的大小根据C编译器系统决定的;

完全自学C(干货) —— 文件_第7张图片

#include 
#include 
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("pf");
		return 0;
	}
	//将代码写入输出缓存区
	fputc('a', pf);
	//睡眠10s,文件内并未写入内容
	Sleep(10000);
	//刷新缓存区
	fflush(pf);
	//睡眠10s,文件内已写入内容
	Sleep(10000);

	//关闭文件也会刷新缓存区
	fclose(pf);
	pf = NULL;
	return 1;
}

案例

  • 通讯录(使用文件存储录入的信息)

你可能感兴趣的:(C,c++,编程语言,c语言,c++,编程语言)