文件操作超详细讲解

1. 文件

1. 数据文件

  • 程序运行时需要读取数据的文件,或者输出数据的文件叫数据文件

2. 文件指针

  • 当我们打开一个文件时,系统会在内存开辟一个文件信息区,这个文件信息区放着文件的相关信息
  • 文件信息区其实是一个结构体变量,结构体变量中放着文件的相关信息,通过文件信息区就可以访问该文件,而文件指针就会指向文件信息区首元素的地址,那么通过文件指针可以直接找到与它相关的文件

3.文件名

文件名包含3部分:文件路径+文件名主干+文件后缀

2. 文件的打开和关闭

> #include <stdio.h>
int main()
{
    
    
	//打开
	FILE* p = fopen("file.txt", "w");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	
	//关闭
	fclose(p);
	p = NULL;
}
  • 文件打开失败返回NULL
  • 第一个参数是文件名,第二个参数是以什么方式打开即文件的使用方式,以w(写的形式)形式打开
  • 如果没有这个文件,会创建一个新的文件,即使有这个文件,它也会销毁这个文件,创建一个新的文件,原来文件的内容也会被销毁

3. 文件的顺序读写

1. 字符输出函数

> #include <stdio.h>
int main()
{
    
    
	//打开
	FILE* p = fopen("file.txt", "w");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 26; i++)
	{
    
    
		fputc(97 + i, p);
	}
	//关闭
	fclose(p);
	p = NULL;
}

在这里插入图片描述
在这里插入图片描述

  • 第一个参数传字符或字符的ascii值,第二个传文件指针

2.字符输入函数

#include <stdio.h>
int main()
{
    
    
	//打开
	FILE* p = fopen("file.txt", "r");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 26; i++)
	{
    
    
		printf("%c", fgetc(p));
	}
	//关闭
	fclose(p);
	p = NULL;
}

在这里插入图片描述
在这里插入图片描述

  • fgetc的参数是一个文件指针,返回字符的ascii值

  • 至于为什么不打印aaaaaaaaa…

  • 为什么不打印aaaaaaaaa…的原因

每次打开文件时,都会有一个文件指针指向文件内容
在这里插入图片描述

  • 注意这个文件指针并不是FILE* p = fopen(“file.txt”, “r”);这里的指针p,指针p是指向文件信息区的,而这个指针是一个全新的指向文件内容的指针,
  • 每次调用fgetc()时,文件指针都会向后指向下一个元素,所以输入到内存的字符不是同一个

3.文本行输出函数

#include <stdio.h>
int main()
{
    
    
	//打开
	FILE* p = fopen("file.txt", "w");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	char arr[] ="aaa";
	fputs(arr, p);
	//关闭
	fclose(p);
	p = NULL;
}

在这里插入图片描述
在这里插入图片描述

4.文本行输入函数

#include <stdio.h>
int main()
{
    
    
	//打开
	FILE* p = fopen("file.txt", "r");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	char arr[20] = {
    
     0 };
	fgets(arr, 5, p);
	printf("%s", arr);
	//关闭
	fclose(p);
	p = NULL;
}

在这里插入图片描述

  • 第一个参数为字符指针,第一个参数为最大拷贝多少个字符,第三个为文件指针
  • 使用时要注意实际向str拷贝的num-1个字符,因为str要末尾要有\0占一个字符
    在这里插入图片描述

4.格式化输出函数

在这里插入图片描述

  • 对于fprintf可以先仿照printf来写,它们参数是只差一个文件指针,最后再补上文件指针即可
#include <stdio.h>
struct s
{
    
    
	char name[20];
	int age;
};
int main()
{
    
    
	struct s s = {
    
     "zhangsan",30 };
	//打开
	FILE* p = fopen("file.txt", "w");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	fprintf(p,"%s %d", s.name, s.age);
	//关闭
	fclose(p);
	p = NULL;
}

在这里插入图片描述

5.格式化输入函数

  • 同样是先仿写scanf,再写fsanf
    在这里插入图片描述
#include <stdio.h>
struct s
{
    
    
	char name[20];
	int age;
};
int main()
{
    
    
	struct s s = {
    
     0 };
	//打开
	FILE* p = fopen("file.txt", "r");
	if (p == NULL)
	{
    
    
		perror("file_fopen");
		return 1;
	}
	//使用
	fscanf(p, "%s %d", s.name, &s.age);
	//关闭
	printf("%s %d", s.name, s.age);
	fclose(p);
	p = NULL;
}

在这里插入图片描述

6.二进制输入

在这里插入图片描述

#include <stdio.h>
struct s
{
    
    
	char name[20];
	int age;
};
int main()
{
    
    
	struct s s = {
    
     "lisi",20 };
	FILE * p = fopen("file.txt", "wb");
		if (p == NULL)
		{
    
    
			perror("file_fopen");
			return 1;
		}
		//使用
		fwrite(&s, sizeof(struct s), 1, p);
		//关闭
		fclose(p);
		p = NULL;
	
}

在这里插入图片描述

7.二进制输入

在这里插入图片描述

struct s
{
    
    
	char name[20];
	int age;
};
int main()
{
    
    
	struct s s = {
    
     0};
	FILE * p = fopen("file.txt", "rb");
		if (p == NULL)
		{
    
    
			perror("file_fopen");
			return 1;
		}
		//使用

		fread(&s, sizeof(struct s), 1, p);
		printf("%s %d", s.name, s.age);
		//关闭
		fclose(p);
		p = NULL;
	
}

在这里插入图片描述

4. 流的概念

  • 流是一个抽象的概念
  • 我们将数据传输到文件,屏幕等外部设备时,我们抽象出来一个流,让流去实现如何将数据传到外部设备上去,我们只负责将数据写到流里,从流里拿数据
  • C语言默认打开三个流:屏幕:标准输出流(stdout),键盘:标准输入流(stdin),屏幕:标准错误流(stderr),三者类型均为FILE*

5.scanf,sprintf

  • scanf将字符串转化为格式化数据
  • sprintf将格式化数据转化为字符串
#include <stdio.h>
struct s
{
    
    
	char name[20];
	int age;
};
int main()
{
    
    
	struct s s = {
    
     "lisi",20};
	char arr[20] = {
    
     0 };
	sprintf(arr, "%s %d", s.name, s.age);
	printf("%s", arr);
	printf("\n");
	struct s tmp = {
    
     0 };
	sscanf(arr, "%s %d", tmp.name, &tmp.age);
	printf("%s %d", tmp.name, tmp.age);
}

在这里插入图片描述

6. 文件的随机读写

1. feek

在这里插入图片描述

在这里插入图片描述

  • 三者分别表示文件开始位置,文件指针当前位置,文件末尾
  • 作用为对指向文件内容的指针进行偏移进行
  • 假设文件里有abcdef
int main()
{
    
    
	FILE*p = fopen("file.txt", "r");
		if (p == NULL)
		{
    
    
			perror("file_fopen");
			return 1;
		}
		//使用
		int ch = 0;
		ch = fgetc(p);//a
		printf("%c", ch);
		ch = fgetc(p);//b
		printf("%c", ch);
		ch = fgetc(p);//c
		printf("%c", ch);
		ch = fgetc(p);//d
		printf("%c", ch);//此时指向e
		fseek(p, -2, SEEK_CUR);
		ch = fgetc(p);//希望打印c
		printf("%c", ch);
		//关闭
		fclose(p);
		p = NULL;
	
}

2.ftell

在这里插入图片描述

  • 告诉我指针偏移量
int main()
{
    
    
	FILE*p = fopen("file.txt", "r");
		if (p == NULL)
		{
    
    
			perror("file_fopen");
			return 1;
		}
		//使用
		int ch = 0;
		ch = fgetc(p);//a
		printf("%c", ch);
		ch = fgetc(p);//b
		printf("%c", ch);
		ch = fgetc(p);//c
		printf("%c", ch);
		ch = fgetc(p);//d
		printf("%c", ch);//此时指向e
		fseek(p, -2, SEEK_CUR);
		ch = fgetc(p);//希望打印c
		printf("%c", ch);
		//打印完后指向d,相对起始位置偏移了3
		printf("%d", ftell(p));
		
		//关闭
		fclose(p);
		p = NULL;
	
}

3.rewind

  • 将文件指针回到起始位置
int main()
{
    
    
	FILE*p = fopen("file.txt", "r");
		if (p == NULL)
		{
    
    
			perror("file_fopen");
			return 1;
		}
		//使用
		int ch = 0;
		ch = fgetc(p);//a
		printf("%c", ch);
		ch = fgetc(p);//b
		printf("%c", ch);
		ch = fgetc(p);//c
		printf("%c", ch);
		ch = fgetc(p);//d
		printf("%c", ch);//此时指向e
		fseek(p, -2, SEEK_CUR);
		ch = fgetc(p);//希望打印c
		printf("%c\n", ch);
		//打印完后指向d,相对起始位置偏移了3
		printf("%d\n", ftell(p));
		rewind(p);
				//偏移量变为0
		printf("%d\n", ftell(p));

		//关闭
		fclose(p);
		p = NULL;
	
}

7.文本文件和二进制文件

  • 根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
  • 数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
  • 如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

8.文件读取结束的判定

  • 用feof,ferror来进行判定,当读取文件结束后,feof()判断结束原因是否为文件读取结束,ferrof判断结束原因是否为发生错误而结束
    在这里插入图片描述
    在这里插入图片描述

9.文件缓冲区

  • 从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。
    • 如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。
  • 缓冲区的大小根
    据C编译系统决定的。

猜你喜欢

转载自blog.csdn.net/wan__xia/article/details/129883209