C —— 文件操作

文件操作

之前都是在内存中运行的代码,

调试窗口一关,数据就销毁了,不管是栈区还是堆区静态区的数据,

因为他们都是存储在内存上的,

要学会文件操作,临时存储数据的选项。

数据库,存储数据

程序在内存中执行,硬盘上执行的是文件,

  • 在程序设计中,谈到的文件是:程序文件、数据文件(从文件功能的角度来分类的)。

    1. 程序文件
  • 源文件(.c)、目标文件(windows环境后缀为 .obj) 、可执行文件(windows环境后缀为.exe)

    1. 数据文件

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

在终端上进行,以终端为对象的,从终端的键盘输入数据,运行显示到显示器上。//这句话有歧义。

在终端上运行的是,从内存中读取的文件,

看一下,之前写的工程,文件名后缀分布。

2.3 文件名

一个文件的唯一的文件标识,以便用户识别和引用。

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

c:\code\test.txt

  1. 文件的打开和关闭

缓冲文件系统中的,

每一个被使用的文件都在内存中开辟了一个相应的文件信息区,存放文件的相关的信息。(文件的名字,文件状态及文件当前的位置)。信息保存在一个结构体变量中,该结构体类型是有系统声明的,名字是 FILE

3.1 文件指针
  • 创建一个FILE*的 指针变量
FILE* pf;//文件指针变量

使pf指向某个文件的文件信息区。(是一个结构体变量)。通过该文件信息区中的信息就能访问该文件。

  • 流的概念

stream,流

——高度抽象的概念。

程序要在不同的环境中被使用,比如:屏幕、硬盘、U盘上、光盘、网络、软盘上,

为了应对这种现象,使用stream来做过度,程序在书写的过程中,不用专门的编写代码,应对不同环境

C语言程序,只要运行起来,就默认打开的3个流:(FILE*)

stdin - 标准输入流 - 键盘

stdout - 标准输出流 - 屏幕

stderr - 标准错误流 - 屏幕


  • fopen()
int main()
{
    FILE* pf = fopen("test.txt","r");//只读不会新建
    if(pf == NULL)
    {
        perror("pf");
        return 1;
    }
    FILE* pf1 = fopen("test.txt","w");//没有的话,会新建一个文件。
    if(pf1 == NULL)
    {
        perror("pf1");
        return 1;
    }
    return 0;
}

使用的方法下面有:就是还含有包不包括新建文件。

  • 是fopen()函数的使用方法

常用

文件使用方式含义如果指定文件不存在
“r“(只读)为了输入数据,打开一个已经 存在的文本文件出错
”w“(只写)为了输出数据,打开一个文本文件建立一个新的文件
”a“(追加)向文本文件尾添加数据建立一个新的文件
“a+”(追加,新建)打开一个文件,在文件尾进行读写建立一个新的文件
  • 文件和硬盘的关系

fopen(),函数的读取是相对于,内存来言的。


  • 输入和输出流函数
    • p文件 34min

FILE函数

  • fgetc() - 的使用
int main()
{
	FILE* pf = fopen("test.bat", "r");
	if (pf == NULL)
	{
		perror("fopen:");
		return 1;
	}
	//读取文件
	int ret = fgetc(pf);//这里是int,为什么?这是规定。
	//printf("%d\n", ret);
	printf("%c\n", ret);//%c - 打印还能理解。
	 ret = fgetc(pf);
	printf("%c\n", ret);
	 ret = fgetc(pf);
	printf("%c\n", ret);
	//关闭文件
	fclose(pf);
	pf = NULL;
    
	return 0;
}
  • fputc()
int main()
{
	fputc('w', stdout);
	fputc('h', stdout);
	fputc('y', stdout);
	//直接打印一排的字母 - why
    
	return 0;
}

stdin - 标准输入流 - 键盘

stdout - 标准输出流 - 屏幕

stderr - 标准错误流 - 屏幕

  • fgetc()
	int ret = fgetc(stdin);
	printf("%c\n", ret);
    ret = fgetc(stdin);
	printf("%c\n", ret);
	ret = fgetc(stdin);
	printf("%c\n", ret);

先输入内容,才能在屏幕上输出,

  • fscanf() 和 fprintf()
	int input = 0;
	fscanf(stdin, "%d", &input);
	fprintf(stdout, "%d", input);
fwrite(&a,sizeof(int),1,pf);
//        元素多大, 几个整型
// 从&a写到pf的地址处。
  • 拷贝文件

int main()
{
	FILE* pfread = fopen("test.txt", "r");
	if (pfread == NULL)
	{
		perror("pfread");
		return 1;
	}
	FILE* pfwrite = fopen("tesst1.txt", "w");
	if (pfwrite == NULL)
	{
		fclose(pfread);
		pfread = NULL;
		perror("pfwrite");
		return 1;
	}
	int ch = 0;
	while ((ch = fgetc(pfread)) != EOF)
	{
		fputc(ch,pfwrite);
	}
	fclose(pfread);
	pfread = NULL;
	fclose(pfwrite);
	pfwrite = NULL;

	return 0;
}

因为,fopen()参数是“r”的话,不会新建一个文件。


针对这三种不同的函数
  • scanf(“%d",&input) - 针对标准输入的格式化的输入语句 - stdin

  • fscanf(stream,“%d”,&input) - 针对所有输入流的格式化的输入语句 - stdin / 文件

  • sscanf() - 从一个字符串中读取一个格式化的数据

  • printf(“%d\n”,input) - 针对标准输出的格式化输出语句 - stdout

  • fprintf(stream,“%d”,input) - 针对所有输出流的格式化输出语句 - stdout / 文件

  • sprintf() - 把一个格式化的数据,转换成字符串

//用结构举例说明
struct S
{
	char arr[10];
	int a;
	double b;
};

int main()
{
	int input = 0;
	scanf("%d", &input);
	printf("%d", input);

	//换一种输入和输出的方法

	int sinput = 0;

	fscanf(stdin,"%d" ,&sinput);
	fprintf(stdout,"%d", sinput);

	//使用sscanf() and sprintf()
	struct S s = { "hello",4,5.5f};
	struct S tmp = { 0 };

	char buf[100] = { 0 };
	//将结构体数据转换成字符串
	sprintf(buf, " % s % d % lf", s.arr, s.a, s.b);
	printf("%s\n", buf);

	//将字符串中的数据转换成一个结构体。
	sscanf(&tmp, "%s %d %lf", s.arr, &(s.a),&( s.b));
	printf("%s %d %lf", s.arr, s.a, s.b);
	return 0;
}
文本文件和二进制文件

根据数据的组织形式,数据文件被称为文本文件或者二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。

FILE*指针相关的相关函数,
  • fseek(pf,-2,SEEK_END) - 调整文件指针

第三个参数,可选值:SEEK_END 、 SEEK_CUR 、SEEK_SET,,current当前,,set ,beginning

  • ftell(pf) - 显示偏移量

  • rewind(pf) - 文件指针回到初始位置

文件读取结束的判定

feof()函数

在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是结束。

而是应用于当前文档读取结束的时候,判断是读取失败结束,还是遇到文件尾结束

  1. 文本文件读取是否结束,判断返回值是否为EOF(fgetc),或者NULL,(fgets)
    • fgetc判断是否为EOF.
    • fgets判断返回值是否为NULL.
    1. 二进制文件的读取结束判断,判断返回值是否实际要读的个数。
    • fread判断返回值是否小于实际要读的个数。
  • 相关代码

int main()
{
	FILE* pfread = fopen("test.txt", "r");
	if (pfread == NULL)
	{
		perror("pf");
		return 1;
	}
	FILE* pfwrite = fopen("test2.txt", "w");
	if (pfwrite == NULL)
	{
		fclose(pfread);
		pfread = NULL;
		return 1;
	}
	//文件打开成功
	//读写文件
	int ch = 0;
	while ((ch = fgetc(pfread)) != EOF)
	{
		//写文件
		fputc(ch, pfwrite);
	}
	if (feof(pfread))
	{
		printf("遇到文件结束标志,文件正常结束\n");
	}
	else if (frerror(pfread))
	{
		printf("文件读取失败\n");
	}
	fclose(pfread);
	pfread = NULL;
	fclose(pfwrite);
	pfwrite = NULL;

	return 0;
}
  • 文件结束判断标志
	int c;
	FILE* fp = fopen("test.txt", "r");
	if (fp == NULL)
	{
		perror("fp");
		return 1;
	}
	while ((c = fgetc(fp)) != EOF)
	{
		putchar(c);
	}
	if (ferror(fp))
		puts("\nwhen reading\n");
	else if (feof(fp))
		puts("\nend of file\n");
	fclose(fp);
	fp = NULL;

文件缓存区

内存中程序在数据区到硬盘的过程中,输入和输出的过程中,都要走缓存区。
window.hSleep(1000);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值