磁盘上的文件,文件是一种存放数据的媒介
一般在程序设计中,文件分为两种:程序文件和数据文件。
.c .h(源程序文件).obj(目标文件).exe(可执行程序文件)类的文件,能够被执行,被编译
程序文件可以操作数据文件
可以被操作,是程序运行时读写的数据
包含三部分:文件路径+文件主干名+文件后缀
eg:c:\user\test.txt
数据文件分为:文本文件和二进制文件
ANSIC标准采用“缓冲文件系统”处理数据文件,[系统自动在内存中为程序中每一个正在使用的文件开辟一块文件缓冲区]
从内存向磁盘输出数据,会先放在缓冲区,如果缓冲区放满了再一起放入磁盘;从磁盘文件读取数据,会先输入到内存缓冲区,装满缓冲区再逐个送入数据区(缓冲区大小由C编译器决定)
也称“文件类型指针”,在输出数据文件时需要先装满磁盘,所以要有存储数据文件,程序会自动建立一个文件信息区[存放数据文件的相关信息]
文件信息区是用来存放文件相关信息的,这些信息保存在一个结构体类型的变量中,FILE类型,系统中有定义(编译器不同结构体中成员有所差异,不过都是大同小异的),我们要维护相关信息就得定义一个FILE*型的变量(文件指针)
通过文件指针可以找到与它关联的文件
文件使用之前要打开文件,使用之后要关闭文件
【1】打开文件
使用函数fopen()
FILE* fopen(const char* filename,const char* mode)
参数包括:文件名+打开方式
打开方式包括:
写法:
1.相对路径
fopen(“test.txt”,“r”);
//表示在当前路径的同级路径下
…/ 表示上一级路径
fopen(“…/test.txt”,“r”);
//表示在上一级路径下
fopen(“…/…/test.txt”,“r”);
//表示在上上级路径下
2.绝对路径
fopen(“C:\code\store\Project2\test.txt”,“r”);
//通过转义字符读取‘\’
【2】关闭文件
int fclose(FILE* stream)
#include
#include
//打开文件
FILE* pf=fopen("test.txt","r");
if(pf==NULL)//可能打开失败返回空指针,用strerror函数打印错误
{
printf("%s\n",strerror(errno));
return 0;
}
//打开成功
//读取文件
//关闭文件
fcolse(pf);//传值调用并不会改变pf本身,因此需要另外置空释放空间
pf=NULL;
注意:
从键盘输入以及输出到屏幕中,屏幕和键盘都是外部设备
键盘———标准输入设备——stdin
屏幕———标准输出设备——stdout
是一个程序默认打开的两个流设备
stdin stdout stderer
这三个流是默认打开的都是FILE*型的
FILE* pf=fopen("test.txt","w");
if(pf==NULL)
{
printf("%s\n",strerror(errno));
return 0;
}
fputc('b',pf);
fcolse(pf);//传值调用并不会改变pf本身,因此需要另外置空释放空间
pf=NULL;
FILE* pf=fopen("test.txt","r");
if(pf==NULL)
{
printf("%s\n",strerror(errno));
return 0;
}
int ch=fgetc(pf);
printf("%c",ch);
fclose(pf);
pf=NULL;
int main()
{
char arr[100]={0};
FILE* pf=fopen("test.txt","r");
if(pf==NULL)
{
printf("%s\n",strerror(errno));
return 0;
}
fgets(arr,100,pf);
printf("%s",arr);//也可以用puts(pf);函数实现输出
fcolse(pf);
pf=NULL;
return 0;
}
int main()
{
char arr[100]={0};
FILE* pf=fopen("test.txt","w");
if(pf==NULL)
{
printf("%s\n",strerror(errno));
return 0;
}
fputs("hello",pf);
fcolse(pf);
pf=NULL;
return 0;
}
int main()
{
char buf[1024]={0};
fgets(buf,1024,stdin);//从标准输入流读取
fputs(buf,stdout);//输出到标准输出流
return 0;
}
这种写法等价于
gets(buf);
puts(buf);
格式化输入函数
fscanf()函数
int fscanf( FILE *stream, const char *format [, argument ]… )
对比int scanf( const char format [,argument]… )
和scanf使用基本相同,但还需要传递一个FILE型的参数
格式化输出函数
fprintf()
int fprintf( FILE *stream, const char *format [, argument ]…)
对比int printf( const char format [, argument]… )
和printf使用基本相同,但还需要传递一个FILE型的参数
例如:fprintf(pf,“%d %f %s”,10,3.14,“hello”);
scanf/printf fscanf/fprintf sscanf/sprintf的区别?
scanf/printf——针对标准输入/输出流的格式化输入/输出语句
fscanf/fprintf——针对所有输入/输出流的格式化输入/输出语句
sscanf/sprintf——从字符串(buffer)中读入到tmp(相同类型结构)/将文件信息转化为字符串(buffer)
int sscanf( const char *buffer, const char *format [, argument ] … );
int sprintf( char *buffer, const char *format [, argument] … );
二进制输出
fwrite()函数
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream )
将buffer中的内容写入stream
二进制输入
fread()函数
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
将stream中的内容读入buffer
由前面的知识,我们知道数据文件分为:文本文件和二进制文件。两者又有什么区别呢?
主要体现在存储形式上的不同,字符都是以ASCII码的形式存储在内存中;而数字在输出到磁盘时,则可能是以ASCII码值形式,也可能是以二进制形式。如果是以ASCII码值形式输出到磁盘,则称为文本文件;如果是以二进制形式存储到磁盘,则称为二进制文件。
举个简单的例子:
int a=10000存储到文件中有两种形式:
feof()应用于当文件读取结束了,判断是读取失败结束还是遇到文件尾结束,而不是用来判断文件是否结束的
EOF-end of file(定义中是-1)
文件读取失败perror()函数打印输入的内容+:+原因
【1】文本文件读取结束判断返回值为EOF(fgetc判断)还是NULL(fgets判断)
【2】二进制文件读取判断返回值是否小于实际要读的个数(fread判断)
if(feof(pf))
printf("error\n");
else if(ferror(pf))
printf("file is end\n");