每次写完程序并运行成功,我们的编译器会自动生成2个文件
1、.cpp文件(源程序文件)
2、.exe文件(可执行文件)
在实际操作中,经常需要把一些输出数据保存下来,在需要时送入内存,此时就需要用到磁盘文件。
文件的构成:
1、文件名(便于识别引用,通常情况下都是自己命名的)
2、路径(用来找到文件,也就是文件的位置,比如在C盘哪个文件夹里面,在文件属性里就可以轻松找到)
3、后缀(代表文件的格式,例如.txt是文本文档,.exe是可执行文件)
文件指针:FILE *fp
用来指向文件的,指针名可自己随意选择。
文件函数
打开文件函数 fopen(成功打开后指向该文件的指针就会被返回,失败返回NULL)
关闭文件函数 fclose
使用方法:fopen("文件名","使用文件方式");
例如:fp=fopen("data.in","rb");
r (只读),如果指定文本文件存在,将文件内的数据输出到屏幕,若文件不存在则会报错
#include <stdio.h>
#include<stdlib.h>
int main()
{
FILE*p;
char ch;
if((p=fopen("test.txt","r"))==NULL) //以只读的方式打开test。
{
printf("ERROR");
exit(0);
}
for(;ch!='\n';)
{
ch=fgetc(p); //ch得到p所指文件中的每一个字符
putchar(ch); //将得到的字符输出到屏幕
}
fclose(p); //关闭文件
}
w(只写),如果指定文本文件存在,将文件打开后,文件中的原数据会全部被清空,写入并只保留新数据;
若不存在则会建立一个新的文件,将文件打开后写入数据
#include <stdio.h>
#include<stdlib.h>
int main()
{
FILE*p; //设置一个文件指针
char ch; //定义一个字符变量
if((p=fopen("test.txt","w"))==NULL) //打开一个叫test的文本文件,只以写的方式,出错时,即返回值为NULL时,输出错误信息
{
printf("ERROR");
exit(0); //关闭所有文件,终止正在执行的程序
}
for(;ch!='\n';) //输入ch知道输入空格。
{
scanf("%c",&ch);
fputc(ch,p); //将字符ch写入p所指向的文件
}
fclose(p);//关闭文件
}
a (追加), 想要保留文件中的原数据不被清空,将"w"改为"a"即可,若文件不存在则会报错
#include <stdio.h>
#include<stdlib.h>
int main()
{
FILE*p; //设置一个文件指针
char ch; //定义一个字符变量
if((p=fopen("test.txt","a"))==NULL) //打开一个叫test的文本文件,只以写的方式,出错时,即返回值为NULL时,输出错误信息
{
printf("ERROR");
exit(0); //关闭所有文件,终止正在执行的程序
}
for(;ch!='\n';) //输入ch知道输入空格。
{
scanf("%c",&ch);
fputc(ch,p); //将字符ch写入p所指向的文件
}
fclose(p);//关闭文件
}
rb(只读) ,如果指定的二进制文件存在,将文件内的数据输出到屏幕,若文件不存在则会报错
wb(只写),如果指定的二进制文件存在,将文件打开后,文件中的原数据会全部被清空,写入并只保留新数据;
若不存在则会建立一个新的文件,将文件打开后写入数据
r+ (读写) ,文本文件,不存在就会报错
w+(读写),文本文件,不存在新建文件
a+ (读写),文本文件,不存在就会报错
文本文件是特殊的二进制文件,两者仅在Windows系统中进行区别,他们的逻辑存储上不同,也就是编码方式不同。
文本文件格式存储时是将值作为字符然后存入其字符编码的二进制,文本文件用‘字符’作为单位来表示和存储数据,比如对于1这个值,文本文件会将其看做字符‘1’然后保存其ASCII编码值(这里假定是ASCII编码)
二进制读写是将内存里面的数据直接读写入文本中,而文本呢,则是将数据先转换成了字符串,再写入到文本中。
但UNTX\Linux并没有区分他们。
读写字符函数
读字符:fgetc(文件指针) //从指针所指向的文件中读入一个字符
写字符:fputc(ch,fp) //把字符变量ch写道fp所指向的文件中去
检测文件是否结束的函数 feof(end of file)
feof(文件指针) //当文件未结束返回0,当文件结束返回非0值
while(!feof(fp)) //返回非0,循环结束
(或者while(!(ch=fgetc(fp))==EOF)//EOF和NULL都是标准库里的宏定义,EOF就是-1,NULL就是0。)
#include <stdio.h>
#include<stdlib.h>
int main()
{
FILE*p1,*p2; //设置2个文件指针
char filename[30],filename1[30],ch; //设置2个字符数组用来输入文件名用
printf("请输入要复制的文件名\n");
gets(filename); //输入文件名,记得带上文件后缀
printf("请输入复制后的文件名:\n");
gets(filename1); //输入新的文件名,记得带上后缀
if((p1=fopen(filename,"rb"))==NULL) //打开被复制的文件
{
printf("ERROR");
exit(0);
}
if((p2=fopen(filename1,"wb"))==NULL) //写入要复制的文件名
{
printf("ERROR");
exit(0);
}
while(!feof(p1)) //用一个检查文件是否结束的函数来判断
{
ch=fgetc(p1);//读出每一个p1指向的文件中的字节,把ch写入到p2指向的文件中去,如果没有p2文件,则会建立一个以filename1字符数组命名的文件;如果存在,文件中的原数据会被清空,只保留新数据
fputc(ch,p2);
}
printf("复制成功");
fclose(p1); //用完之后,为了避免不必要的操作干扰读写,要关闭文件,即断掉文件指针与文件的联系
fclose(p2);
}
字符串的读写
fgets函数:fgets(str,n,fp);
从fp指向的文件读入一个长度为n-1的字符串,存放在字符数组str中,成功返回str地址,失败返回NULL
fputs函数:
fputs(str,fp);
把str所指向的字符串写入fp所指向的文件中,成功返回0,失败返回非0
#include <stdio.h>
#include<stdlib.h>
int main()
{
FILE*fp;
char filename[40],string[30]; //定义一个字符数组来存储文件里的信息
printf("请输入要打开的文件名\n");
gets(filename);
if((fp=fopen(filename,"r"))==NULL) //以只读的方式打开文件打开文件
{
printf("ERROR");
exit(0);
}
fgets(string,20,fp); //将fp所指的文件中的20字符读取给字符串string
fclose(fp); //关闭文件
puts(string); //以字符串形式输出string
}
格式化方式读写文本文件:
fprintf函数:fprintf(文件指针,格式字符串,输出列表)
fscanf函数:fscanf(文件指针,格式字符串,输入列表)
#include <stdio.h>
#include<stdlib.h>
int main()
{
int i=3;
float j=4.567;
char string[20];
FILE*fp;
if((fp=fopen("test.txt","r+"))==NULL) //以读写的方式打开test文件
{
printf("ERROR");
exit(0);
}
fscanf(fp,"%s",string); //把文件中的不断裂字符串写入字符数组string中,然后停止
puts(string); //输出文件中的字符串
fprintf(fp,"%3d %6.4f",i,j); //以%3d,%6.4的格式在文件中输入整形变量i和浮点型变量j
fclose(fp); //关闭文件
return 0;
}
数据块读写:用二进制的方式块状的读写文件中的信息
例如结构体类型的数据
创建一个文件,将结构体类型信息以二进制的形式写入文件,然后再从文件中读出信息打印到屏幕上。
分离版
#include <stdio.h>
#include <stdlib.h>
#define LEN 15 //结构体中字符串的长度
#define NUM 3 //要输入数据学生的个数
struct Student //定义学生结构体
{
char name[LEN];
int num;
int age;
char add[LEN];
}Stud[NUM]; //将数据先存放在结构体数组之中
int main()
{
FILE*fp;
int i;
if((fp=fopen("student","wb"))==NULL) //建立一个叫student的文件以二进制形式进行打开进行写入操作,
{
printf("ERROR");
exit(0);
}
printf("请输入学生数据\n");
for(i=0;i<NUM;i++) //
{
scanf("%s%d%d%s",&Stud[i].name,&Stud[i].num,&Stud[i].age,&Stud[i].add);//输入学生数据信息
}
for(i=0;i<NUM;i++)
{
if(fwrite(&Stud[i],sizeof(struct Student),1,fp)!=1)//每次写一个结构体变量所占的字节,将输入的数据写入文件
{
printf("write error");
}
}
fclose(fp); //关闭文件
}
#include <stdio.h>
#include<stdlib.h>
#define LEN 15
#define NUM 3
struct Student
{
char name[LEN];
int num;
int age;
char add[LEN];
}Stud[NUM];
int main()
{
FILE*fp;
int i;
if((fp=fopen("student","rb"))==NULL) //以二进制的方式读取
{
printf("ERROR");
exit(0);
}
printf("姓名 学号 年龄 地址\n");
for(i=0;i<NUM;i++) //将数据每次一个结构体变量所占字节的个数的数据赋给结构体变量
{
if(fread(&Stud[i],sizeof(struct Student),1,fp)!=1)
{
printf("read error");
}
}
for(i=0;i<NUM;i++) //输出结构体变量的各个成员,输出数据
{
printf("%s %4d %4d %4s",Stud[i].name,Stud[i].num,Stud[i].age,Stud[i].add);
printf("\n");
}
fclose(fp); //关闭文件
}
结合版
#include <stdio.h>
#include<stdlib.h>
#define LEN 15 //结构体中字符串的长度
#define NUM 3 //要输入数据学生的个数
struct Student //定义学生结构体
{
char name[LEN];
int num;
int age;
char add[LEN];
}Stud[NUM]; //将数据先存放在结构体数组之中
int main()
{
FILE*fp;
int i;
if((fp=fopen("student","wb"))==NULL) //建立一个叫student的文件以二进制形式进行打开进行写入操作,
{
printf("ERROR");
exit(0);
}
printf("请输入学生数据\n");
for(i=0;i<NUM;i++) //
{
scanf("%s%d%d%s",&Stud[i].name,&Stud[i].num,&Stud[i].age,&Stud[i].add);//输入学生数据信息
}
if((fp=fopen("stduent","rb"))==NULL) //以二进制的方式读取
{
printf("ERROR");
exit(0);
}
printf("姓名 学号 年龄 地址\n");
for(i=0;i<NUM;i++) //输出结构体变量的各个成员,输出数据
{
printf("%s %4d %4d %4s",Stud[i].name,Stud[i].num,Stud[i].age,Stud[i].add);
printf("\n");
}
fclose(fp); //关闭文件
}