概述文件操作

目录

前言:

文件打开和关闭:

打开函数 fopen

关闭函数 fclose

输入输出函数:

fpuc - 把字符写入文件中

fgetc - 从文件中读取字符

fputs - 写入字符串到文件中

fgets - 从文件中读取字符串

fprintf - 格式化写入文件

fscanf - 从文件中读取格式化数据

fwrite - 二进制写入文件

fread - 从文件中读取二进制

随机读写 

fseek - 将指针切到某位

ftell - 计算偏移量

rewind - 切回起始位置

文本文件和二进制文件

文件读取结束的判定

文件缓冲区


前言:

本篇重点对于文件打卡和关闭 及 输入输出函数、随机读写函数进行学习和理解 。

关于文件的概念系列知识不再详述。

对于输入输出 切记是站在程序的角度来说的。程序输出数据或程序输入数据

随机读取实际上是切换指针的位置

文件打开和关闭:

打开函数 fopen

FILE* fopen(const char* filename, const char* mode) //(文件名。打开方式)

关闭函数 fclose

int fclose(FILE* stream)  //(文件指针)

int main()
{
	FILE* pf = fopen("test.txt", "r");
    //打开文件
	if (pf == NULL)
	{
		perror("fopen:");
		return;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

打开函数fopen 的第一个参数是要打开的文件名 ,第二个参数是打开方式

其中常用的打开方式有 "r"、"w"、"a"、"rb"、"wb"....

若不能成功打开,返回空指针,因此我们需要对返回值进行判断,若为空指针必须提前结束。

关闭函数fclose 的参数是文件指针。

不能是空指针。

输入输出函数:

我们在开始之前 再次重申

对于输入输出 切记是站在程序的角度来说的。程序输出数据或程序输入数据

其次再说一下流,流是什么?我不知道。我知道什么?

我想写程序到硬盘、到文件、到屏幕。。。但是怎么写进去我不知道

我们抽象有一个流在我和外部设备之间,我只是一个什么不懂的程序员,所以我把数据写到流中,再让流写入这些外部设备,流是怎么实现的呢,我也不知道。

我还知道什么?

只要一个C程序运行 这三个标准xx流 是默认打开的
标准输入流 stdin //键盘
标准输出流 stdout //屏幕上
标准错误流 stderr  //屏幕

ok 足够了 让我们开始下面的学习:

fpuc - 把字符写入文件中

适用所有输出流

int fputc(int character, FILE * stream);

int main()
{
 //打开文件
 FILE* pf = fopen("test.txt","w");//写入方式
 if(pf == NULL)
 {
   perror("fopen");
   return ;
 }

 //写入文件,程序输出
 fputc('c',pf);

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

fgetc - 从文件中读取字符

适用所有输入流

int fgetc ( FILE * stream );  

int main()
{
 //打开文件
 FILE* pf = fopen("test.txt","r");//只读方式
 if(pf == NULL)
 {
   perror("fopen");
   return ;
 }

 //读取文件,程序输入
 char c = fgetc(pf);//创建变量接收
 printf("%c",c);

 //关闭文件
 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)
 {
   perror("fopen");
   return ;
 }

 //写入文件 程序输出
 fputs("abc\n",pf);//字符串中有\n 才会换行
 fputs("def",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)
 {
   perror("fopen");
   return ;
 }

 //读取文件,程序输入
 char c[256] = {0};
 fgets(c,256,pf);//第二个参数实际读取的是n-1
 printf("%s",c);
 fgets(c,256,pf);//读取下一行
 printf("%s",c);

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

fprintf - 格式化写入文件

适用所有输出流

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

看不懂?简单,再看一下printf

int printf ( const char * format, ... );发现就多出来一个流 pf
struct S 
{
   char name[20];
   int age ;
   double d;
};
int main()
{
 struct S s={"张三",20,95.5};
 //打开文件
 FILE* pf = fopen("test.txt","w");//写入方式
 if(pf == NULL)
 {
   perror("fopen");
   return ;
 }

 //写入文件 程序输出
 fprintf(pf,"%s %d %lf",s.name,s.age,s.d);

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

fscanf - 从文件中读取格式化数据

适用所有输入流

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

struct S 
{
   char name[20];
   int age ;
   double d;
};
int main()
{
 struct S s={0};
 //打开文件
 FILE* pf = fopen("test.txt","r");//只读方式
 if(pf == NULL)
 {
   perror("fopen");
   return ;
 }

 //读取文件 程序输入
 fscanf(pf,"%s %d %lf",s.name,&s.age,&s.d);
 printf("%s %d %lf",s.name,s.age,s.d);

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

fwrite - 二进制写入文件

适用于文件

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

struct S 
{
   char name[20];
   int age ;
   double d;
};
int main()
{
 struct S s={"张三",20,95.5};
 //打开文件
 FILE* pf = fopen("test.txt","wb");//二进制 写入方式
 if(pf == NULL)
 {
   perror("fopen");
   return ;
 }

 //写入文件 程序输出
 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);

struct S 
{
   char name[20];
   int age ;
   double d;
};
int main()
{
 struct S s={0};
 //打开文件
 FILE* pf = fopen("test.txt","rb");//二进制 读方式
 if(pf == NULL)
 {
   perror("fopen");
   return ;
 }

 //读取文件 程序输入
 fread(&s,sizeof(struct S),1,pf);
 printf("%s %d %lf",s.name,s.age,s.d);
 

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

随机读写 

本质上是切换指针的位置 ,下面的函数都是为切换指针服务的 

本次三个函数我们综合一个例子上一起看, 方便理解

fseek - 将指针切到某位

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

(流 , 偏移量(相对于起始位置),位置);

其中origin有三个选项, SEEK_CUR  当前位置 、SEEK_SET 起始位置 、SEEK_END 末尾位置

ftell - 计算偏移量

long int ftell(FILE* stream);

rewind - 切回起始位置

void rewind(FILE* stream);

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if(pf ==NULL)
	{
		perror("fopen");
		return;
	}
	//读文件
	int ch = fgetc(pf);
	printf("%c ", ch);//a

	ch = fgetc(pf);
	printf("%c ", ch);//b

	fseek(pf, 2, SEEK_CUR);
	ch = fgetc(pf);//e
	printf("%c ", ch);

	fseek(pf, -5, SEEK_CUR);
	ch = fgetc(pf);//a
	printf("%c ", ch);

	long pos = ftell(pf);
	printf("%ld ", pos);//1

	rewind(pf);//回到起始位置
	pos = ftell(pf);
	printf("%ld ", pos);//0


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

文本文件和二进制文件

根据数据存储方式,分为文本文件 和 二进制文件。

文本文件在内存中以二进制存储,然后转到外存前转成ASCII码值的形式

二进制文件则一直使用二进制的方式存储

文件读取结束的判定

谨记 feof函数是在读取结束后 判断是读取失败结束还是读到文件尾结束 。而非判断是否结束

判断文件结束:

文本文件:看返回值是EOF或NULL判断

如fgetc返回EOF;fgets返回NULL

二进制文件:根据返回值是否小于实际要读取的个数判断

文件缓冲区

从内存向磁盘输出数据,不会直接输送,会先输送到内存的缓冲区 然后如果缓冲区满了再一起输送。

同理,从磁盘输入数据,先读取数据,会先到缓冲区,然后缓冲区满了再逐个送到程序数据区 

缓冲区的大小是根据C编译系统决定的。

 这里有一个例子,我们看一下。

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10环境测试
int main()
{
FILE*pf = fopen("test.txt", "w");
fputs("abcdef", pf);//先将代码放在输出缓冲区
printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
Sleep(10000);
printf("刷新缓冲区\n");
fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
//注:fflush 在高版本的VS上不能使用了
printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
Sleep(10000);
fclose(pf);
//注:fclose在关闭文件的时候,也会刷新缓冲区
pf = NULL;
return 0;

值得注意的是 在fclose关闭文件时,也会刷新缓冲区。

因此我们大概了解,对于文件操作,我们要通过刷新缓冲区,或者在文件操作结束时关闭文件

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值