【C语言】文件操作

1、文件指针

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

2、打开文件fopen和关闭文件fclose

FILE * fopen ( const char * filename, const char * mode );

filename为文件命,如果打开的文件在工程目录下需要表明文件的绝对位置,mode为文件的方式。

文件使用方式含义如果指定文件不存在
"r"(只读)为了输入数据,打开一个已经存在的文文件出错
"w"(只写)为了输出数据,打开一个文本文件,如果文件存在,会将原文件的内容销毁建立一个新的文件
"a"(追加)向文本文件尾添加数据建立一个新的文件
"rb"(只读)为了输入数据,打开一个二进制文件出错
"wb"(只写)为了输出数据,打开一个二进制文件建立一个新的文件
"ab"(追加)向一个二进制文尾添加数据出错
"r+"(读写)为了读和写,打开一个文本文件出错
"w+"(读写)为了读和写,建立一个新的文件新建一个新的文件
"a+"(读写)打开一个文件,在文件尾进行读写建立一个新的文件
"rb+"(读写)为了读和写打开一个二进制文件出错
"wb+"(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
"ab+"(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件
int fclose ( FILE * stream );

fclose:关闭文件的函数

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
        return 0;
	}
	//写文件
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

3、文件的顺序读写

1、字符输出函数fputc

int fputc ( int character, FILE * stream );

将一个字符写入到输出流,如果成功,返回写入字符的ASCAII码值,如果失败返回EOF

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
	    return 0;
    }
	//写文件
	for (int i = 'a'; i <= 'z'; i++)
	{
		fputc(i, pf);
	}

	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

2、字符输入函数fgetc

int fgetc ( FILE * stream );

从流里得到一个字符,成功返回读到的字符,如果文件结果或者读取错误返回EOF

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
		return 0;
	}
	int ch = 0;
	//读文件
	ch = fgetc(pf);
	printf("%c\n",ch);

	ch = fgetc(pf);
	printf("%c\n",ch);

	ch = fgetc(pf);
	printf("%c\n",ch);
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

3、文本输出函数fputs

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

写入一个字符串,成功返回一个非负值,失败返回EOF

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
        return 0;
	}
	//写文件
	fputs("abcdef", pf);

	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

4、文本输入函数fgets

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

从sream中读取字符串到一个字符数组,num为最大的读取数(实际读的个数为num-1个),成功返回这个字符数组,读取失败或者读取结束返回NULL

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
        return 0;
	}
	//读文件
	char buf[100] = {0};
	fgets(buf, 3, pf);
	printf("%s\n", buf);

	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

5、格式化输出函数fprintf

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

将格式化的数据写到stream 

#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct Stu
{
	char name[5];
	int age;
	char sex[5];
}Stu;
int main()
{
	Stu s1 = { "lisi",20,"male" };
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		printf("open file for writing:%s", strerror(errno));
		return 0;
	}
	fprintf(pf, "%s %d %s", s1.name,s1.age, s1.sex);

	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

6、格式化输入函数fscanf

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

 将格式化的数据读入stream

#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct Stu
{
	char name[5];
	int age;
	char sex[5];
}Stu;
int main()
{
	Stu s1 = { "lisi",20,"male" };
	Stu s2 = { 0 };
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		printf("open file for reading:%s", strerror(errno));
		return 0;
	}
	fscanf(pf, "%s %d %s", s2.name, &s2.age, s2.sex);
	printf("%s %d %s", s2.name, s2.age, s2.sex);
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

 7、二进制输出fwrite

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

从ptr开始,写入count*size大小的数据到stream

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct Stu
{
	char name[10];
	int age;
	char sex[10];
}Stu;
int main()
{
	Stu s[2] = { {"lisi",20,"male"},{"zhangsan",18,"female"}};
	FILE* pf = fopen("test.txt", "wb");
	if (NULL == pf)
	{
		printf("open file for writing:%s", strerror(errno));
		return 0;
	}
	//写文件
	fwrite(s, sizeof(Stu), 2, pf);
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

8、二进制输出fread

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

 从stream中读取大小为size*count的数据,返回成功读取到的元素个数

#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct Stu
{
	char name[10];
	int age;
	char sex[10];
}Stu;
int main()
{
	Stu s[2] = {0};
	FILE* pf = fopen("test.txt", "rb");
	if (NULL == pf)
	{
		printf("open file for reading:%s", strerror(errno));
		return 0;
	}
	//读文件
	fread(s, sizeof(Stu), 2, pf);
	for (int i = 0; i < 2; i++)
	{
		printf("%s %d %s \n", s[i].name, s[i].age,s[i].sex);

	}
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

需要注意fread函数返回的是读取的元素个数,所以当返回值小于count的时候说明数据已经全部读完

4、对比scanf/fscanf/sscanf/printf/fprintf/sprintf

scanf从标准输入流(stdin)上进行格式化输入的函数

printf向标准输出流(stdout)上进行格式化的输出函数

fsacnf可以从标准输入流(stdin)或者指定的文件流上读取格式化的数据

fprintf把数据按照格式的方式输出到标准输出流(stdout)或者指定的文件流

sscanf将字符串转化成格式化的数据

int sscanf ( const char * s, const char * format, ...);

sprintf将格式化的数据转化成字符串

int sprintf ( char * str, const char * format, ... );
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct Stu
{
	char name[10];
	int age;
	char sex[10];
}Stu;
int main()
{
	Stu s= {"zhangsan",12,"male"};
	char buf[100];
	sprintf(buf,"%s %d %s", s.name, s.age, s.sex);
	printf("%s", buf);
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct Stu
{
	char name[10];
	int age;
	char sex[10];
}Stu;
int main()
{
	Stu s1= {"zhangsan",12,"male"};
	Stu s2 = { 0 };
	char buf[100];
	sprintf(buf,"%s %d %s", s1.name, s1.age, s1.sex);
	sscanf(buf, "%s %d %s", s2.name, &s2.age, s2.sex);
	printf("%s %d %s", s2.name,s2.age,s2.sex);
	return 0;
}

5、文件的随机读写

1、fseek

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

根据文件指针的位置和偏移量来定位文件指针

offset为偏移量,origin为起始位置

origin有三个状态

1.SEEK_SET 文件的开始位置

2.SEEK_CUR当前文件指针所指的位置

3.SEEK_END文件结束的位置

比如:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
	FILE* pw = fopen("test.txt", "w");
	if (NULL == pw)
	{
		printf("open file for writing: %s", strerror(errno));
		return 0;
	}
	fputs("abcdef", pw);
	fflush(pw);//fputs会把数据先写入缓存区,而不是直接进文件,所以需要刷新缓冲区,让文件写入,方便后面的读
	FILE* pr = fopen("test.txt", "r");
	if (NULL == pr)
	{
		printf("open file for reading:%s", strerror(errno));
		return 0;
	}
	//直接读到f
	fseek(pr, -1, SEEK_END);
	int ch = 0;
	ch = fgetc(pr);
	printf("%c", ch);
	fclose(pr);
	pr = NULL;
	
	//将x写到c的位置

	fseek(pw, 2, SEEK_SET);
	fputc('x', pw);
	fclose(pw);
	pw = NULL;
	return 0;
}

 

2、ftell

long int ftell ( FILE * stream );

 返回文件指针相对于起始位置的偏移量

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
		return 0;
	}
	int ch = 0;
	//读文件
	ch = fgetc(pf);
	printf("%c\n",ch);

	ch = fgetc(pf);
	printf("%c\n",ch);

	ch = fgetc(pf);
	printf("%c\n",ch);

	//进行3次读取后,文件指针与起始位置的偏移量应该为3
	printf("%d\n", ftell(pf));
	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

3、rewind

void rewind ( FILE * stream );

 让文件指针的位置回到文件的起始位置

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		printf("open file for writing :%s", strerror(errno));
		return 0;
	}
	int ch = 0;
	//读文件
	ch = fgetc(pf);
	printf("%c\n",ch);

	ch = fgetc(pf);
	printf("%c\n",ch);

	ch = fgetc(pf);
	printf("%c\n",ch);

	//进行3次读取后,文件指针与起始位置的偏移量应该为3
	printf("%d\n", ftell(pf));

	//将文件指针的位置回到文件的起始位置
	rewind(pf);
	printf("%d\n", ftell(pf));

	//关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

6、文件拷贝

知道文件的输入输出后,我们就可以写一个文件拷贝的代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
	FILE* pr = fopen("data1.txt", "r");
	FILE* pw = fopen("data2.txt", "w");
	if (NULL == pr)
	{
		printf("open file for reading :%s", strerror(errno));
		return 0;
	}
	if (NULL == pw)
	{
		printf("open file for writing :%s", strerror(errno));
		//读数据的文件指针已经打开,需要关闭
		fclose(pr);
		pr = NULL;
		return 0;
	}
	char buf[1000] = { 0 };
	while (fgets(buf, 1000, pr))//读文件
	{
		//写文件
		fputs(buf, pw);
	}
	

	//关闭
	fclose(pw);
	fclose(pr);
	pw = NULL;
	pr = NULL;
	return 0;
}

7、二进制文件与文本文件

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

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

8、文件读取结束的标志

1、被错误使用的feof

feof函数的返回值直接用来判断文件是否结束,而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束

文本文件读取是否结束

fgetc判断是否为EOF

fgets判断是否为NULL

二进制文件的读取结束判断

fread的返回值是否小于实际要读的个数

#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);
}

9、文件缓冲区 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值