深入理解文件操作:从数据持久化到读写流的全面指南

1.为什么使用文件

因为我们想记录数据,在内存中的数据当设备重启就会消失,而存放在硬盘里面就不会消失,从而做到了数据的持久化

2.什么是文件

文件是计算机系统中存储数据的基本单位,从功能角度大概可以分为两类文件

  • 程序文件:可执行文件,例如.c文件.cpp文件.exe文件
  • 数据文件:存放数据的文件,可以是文本文件,也可以是二进制文件
  • 文件名:用来标识一个文件的唯一性,由文件路径,文件名和后缀构成

3.文件的打开和关闭

每一个被使用的文件都会在内存里面创建一个文件信息区,该文件信息区包含该文件的所有信息,文件名,文件内容,文件位置等等,它们都存放在一个由系统声明的一个结构体中,名字叫做FILE

所以我们创建一个文件变量指针,就能找到与之关联的文件

每个文件对应的文件信息区是各不相同的

我们使用fopen来打开文件,fcolse来关闭文件

FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );

常见的打开方式有

 4. 文件的顺序读写

4.1 顺序读写函数介绍

这些函数在c++网站上均可以查到使用方法,就不在这里赘述了 

我们来介绍一下什么是流

流:类似于水流,我们可以理解一下,这里的流指的是数据流

在C语言中我们常见的有标准有

  • 标准IO流:标准输入流(stdin)、标准输出流(stdout)和标准错误流(stderr)
  • 文件IO流:文件输入流(File input stream)和文件输出流(File output stream)

还有一个概念,什么叫做输入,什么叫做输出

大概可以这样表示

4.2对比一组函数

如果你有兴趣,可以研究一下下面的函数

scanf/fscanf/sscanf

printf/fprintf/sprintf

#include <stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//操作文件
	int arr[10] = {1,2,3,4,5};
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		fprintf(pf, "%d", arr[i]);
	}
	
	fclose(pf);
	pf = NULL;
	return 0;
}

5. 文件的随机读写

5.1 fseek 

int fseek ( FILE * stream, long int offset, int origin );

该函数的作用是:Reposition stream position indicator也就是重新定位流位置指示器

offset是需要偏移几个字节

origin是选择这三项:SEEK_SET、SEEK_CUR、SEEK_END,也就是文件的开头,当前的位置和,文件结束的位置

举个栗子

#include <stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//操作文件
	char c=0;
	fputs("abcdef", pf);
	rewind(pf);
	fseek(pf, 2, SEEK_SET);
	c=fgetc(pf);
	printf("%c", c);
	fseek(pf, 0, SEEK_CUR);
	c = fgetc(pf);
	printf("%c", c);
	fseek(pf, -4, SEEK_END);
	c = fgetc(pf);
	printf("%c", c);
	
	fclose(pf);
	pf = NULL;
	return 0;
}

 

5.2 ftell 

long int ftell ( FILE * stream );

该函数的作用是:Get current position in stream也就是获取流中的当前位置

#include <stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//操作文件
	int i=0;
	fputs("abcdef", pf);
	rewind(pf);
	fseek(pf, 2, SEEK_SET);
	i = ftell(pf);
	printf("%d ", i);
	fseek(pf, 0, SEEK_CUR);
	i = ftell(pf);
	printf("%d ", i);
	fseek(pf, -4, SEEK_END);
	i = ftell(pf);
	printf("%d", i);

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

5.3rewind

void rewind ( FILE * stream );

该函数的作用是:Set position of stream to the beginning也就是设置流的起始位置

#include <stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//操作文件
	int i=0;
	fputs("abcdef", pf);
	fseek(pf, -4, SEEK_END);
	i = ftell(pf);
	printf("%d ", i);
	fgetc(pf);
	i = ftell(pf);
	printf("%d ", i);
	rewind(pf);
	i = ftell(pf);
	printf("%d ", i);



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

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

现在我们用写的方式打开一个文件,并给它里面放一些二进制的内容

我们看当前目录确实出现了一个text.txt文件,里面的内容是二进制代码

我们是用二进制方式打开

根据数据的组织形式,可以分为二进制文件和文本文件

  • 数据在内存中以二进制形式存储,如果不加转换就放入外存,就是二进制文件
  • 数据如果在存储之前转化为ASCII码再放入外存,那么就属于文本文件。

7. 文件读取结束的判定

7.1 被错误使用的feof 

int feof ( FILE * stream );

该函数的作用是判断当文件读取结束时,使用feof来判断文件是以什么方式结束的

fgetc结束时返回EOF,fgets结束时返回NULL,fread结束时返回一个整型

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
	int c = 0;
	FILE* pf = fopen("data.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//操作文件
	const char *arr = "abcdef";
	fputs(arr, pf);
	rewind(pf);
	while ((c=fgetc(pf) )!= EOF)
	{
		putchar(c);
	}
	printf("\n");
	if (ferror(pf))
	{
		printf("读取时发生错误\n");
	}
	else if(feof(pf))
	{
		printf("文件成功读取到结束\n");
	}
	fclose(pf);
	pf = NULL;
	return 0;

}

  • 33
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值