文件的操作

1.什么是文件

文件就是存储在我们电脑中的一些数据,我们一般说的文件分为两种:程序文件和数据文件

程序文件

包括源程序文件(.c文件),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)

数据文件

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

我们这里讨论的就是数据文件

2.文件的类型

数据文件有两种存储模式,分别问二进制文件和文本文件;

二进制文件

电脑中的数据都是以二进制的形式存储的,如果不转换为其他的形式输出到外存,那么就是二进制文件

文本文件

如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。

3.文件指针

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的信息,(如文件的名字,文件的状态和文件的位置等。这些信息是保存在一个结构体变量中的。该结构体类型是由系统申明的,取名FILE。我们打开一个文件的时候,系统会返回一个文件指针来操作这个结构体的变量。

我们打开文件时用fopen这个函数,fclose这个函数来关闭文件。就像我们要对一个瓶子里面的东西进行使用,我们的第一步就是打开瓶盖,使用完之后再盖上盖子

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

在这里插入图片描述
我们可以写一些代码来看看如何操作

#include <stdio.h>
int main(){
	FILE* pf;
	pf=fopen("test.txt","w");//第一个参数是文件的路径,以写的方式打开,如果文件不存在就会创建一个新的文本文件
	if(pf!=NULL){//如果文件打开失败,会返回NULL,如果不为空,才能对文件进行操作
		//文件操作
		fclose(pf);//文件使用结束要关闭文件。
	}
	return 0;
}

4.文件的顺序读写

字符输入/输出函数

int fgetc ( FILE * stream );//字符输入函数,从文件中读取字符到程序中
int fputc ( int character, FILE * stream );//字符输出函数,往文件中写入字符

这两个函数只能在文件里进行存取单个字符的操作
例如:

fputc

#include <stdio.h>
int main(){
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 26; i++) {//把26个字母写进文本文件中,写完一个pf会自动挪到下一个位置进行写入,不会覆盖。
		fputc('a' + i, pf);
	}
	fclose(pf);
	pf=NULL;
	return 0;
}

fgetc

#include <stdio.h>
int main(){
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	int ch = 0;
	while ((ch=fgetc(pf))!=EOF)//fgetc函数读到一个字符之后指针就会指向下一位。如果读到了文件的末尾,fgetc会返回EOF
	{
		printf("%c ", ch);
	}
	fclose(pf);//一定要记得关闭文件指针
	pf=NULL;
	return 0;
}

文本行输入/输出函数

fputs

int fputs ( const char * str, FILE * stream );

int main() {
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	fputs("hello\n", pf);
	fputs("world\n", pf);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}

fgets

char * fgets ( char * str, int num, FILE * stream );

int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	char arr[100];
	fgets(arr, 3, pf);//第一个参数是数组名,用来接收字符串,第二个参数是int类型,会读取n-1个字符
	//如果再调用,第一行没读完继续,如果读完了就会跳到第二行,
	fgets(arr, 2, pf);
	printf("%s", arr);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}

格式化输入/输出函数

fprintf

int fprintf ( FILE * stream, const char * format, … );

struct S {
	char name[20];
	int age;
	double score;
};

int main() {
	struct S s = { "zhangsan",20,90.2 };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	fprintf(pf, "%s %d %f", s.name, s.age, s.score);//这个函数跟printf函数非常相似,
	//只是第一个参数增加了一个文件指针,把结构体的数据写到了文件里

	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}

在这里插入图片描述

fscanf

int fscanf ( FILE * stream, const char * format, … );

struct S {
	char name[20];
	int age;
	double score;
};
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	struct S s = { 0 };
	fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.score));//这个函数和scanf很像,把文件中的数据格式化的读出来
	printf("%s %d %f", s.name, s.age, s.score);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}

在这里插入图片描述

二进制输入/输出函数

swrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

int main() {
	struct S s = { "zhangsan",20,90.2 };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	fwrite(&s, sizeof(struct S), 1, pf);//第一个参数就是一个元素地址,第二个参数传入每个元素的大小,第三个参数传入元素个数
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}

在这里插入图片描述

fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

int main() {
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	struct S s = { 0 };
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s %d %f", s.name, s.age, s.score);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}

5.文件的随机读写

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

这个函数可以调整读取字符指针的位置。第三个参数有三个取值,决定了偏移的方式,详情仔细看代码

SEEK_SET	//从文件的开始往右偏移offset个字符读取
SEEK_CUR	//从文件的中间往右偏移offset个字符读取
SEEK_END	//从文件的末尾往左偏移offset个字符读取

这么说可能比较抽象,我用代码给大家解释一下,文件中存储了这些子符
在这里插入图片描述

int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen():");
		return 1;
	}
	fseek(pf, 2, SEEK_SET);//从文件的开头往右偏移2个字符读取放到pf文件指针,就会读取到c
	int ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen():");
		return 1;
	}
	int ch = fgetc(pf);
	fseek(pf, 2, SEEK_CUR);//从文件的中间开始读,上一个fgetc已经读取一个字符,文件指针会向右偏移一个,那么再偏移两个字符就是d
	ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen():");
		return 1;
	}
	fseek(pf, -3, SEEK_END);//从文件的末尾往左偏移两个字符,第二个参数是负数.
	int ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

6.文件的结束

int feof ( FILE * stream );

这个函数很多人容易用错,这个函数不是判定文件是否结束,而是判断是否是正常的读取到了文件的末尾,还是中途出现错误而结束,如果正常读到了文件末尾结束返回非0值。其他错误返回0。

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int c; // 注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if(!fp) {
        perror("File opening failed");
        return EXIT_FAILURE;
   }
 //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
   { 
       putchar(c);
   }
 //判断是什么原因结束的
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
}

这就是C语言中比较容易用到的一些操作,如果有错误的地方欢迎在评论区留言,一起进步,谢谢。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值