文件指针
文件是指存储在存储介质上的数据的集合。C++将文件看作是由一个一个字符(字节)的数据顺序组成的。按照文件中数据的存放形式可以将文件分为:ASCII文件和二进制文件。 把一个文本文件读入内存时,要将ASCII码转换成二进制码,而把文件以文本方式写入磁盘时,也要把二进制码转换成ASCII码,因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换
“文件指针”是指表示读写文件的文件位置指示器。一个文件指针总是和一个文件相关联,当文件每一次打开时,文件指针都指向文件的开始,随着对文件进行操作,文件指针不断地在文件中移动,并一直指向最新处理的字符(字节)位置。
对文件的读写操作方式有两种方式:顺序文件操作和随机文件操作。程序对每一个文件都使用了一个单独的FILE结构来处理。
typedef struct{ int _fd;//文件号 int _cleft;//缓冲区中剩余字符 int _mode;//文件操作模式 char *_nextc;//下一个字符位置 char *_buff;//文件缓冲区位置 }FILE:
与文件处理相关的类及其继承关系结构图
打开文件
File *fp;
fp=fopen(文件名,文件的使用方式);
文件使用方式由r,w,a,t,b,+六个字符拼成
r(read): 读,用“r”打开一个文件时,该文件必须已经存在,且只能从该文件读出
w(write): 写,用“w”打开的文件只能向该文件写入。若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件
a(append): 追加,若要向一个已存在的文件追加新的信息,只能用“a”方式打开文件。但此时该文件必须是存在的,否则将会出错
t(text): 文本文件,可省略不写
b(banary): 二进制文件
+: 读和写
在打开一个文件时,如果出错,fopen将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作,并作相应的处理。
if((fp=fopen("c:\\hzk16","rb")==NULL){ printf("\nerror on open c:\\hzk16 file!"); exit(1);}
关闭文件
fclose(文件指针);顺利关闭文件返回0,佛足额返回EOF(-1)
FILE *fp...int i = fclose(fp);if(i=0) cout<<"close sucessed!!"<<<"colse failed!!"<
顺序文件操作
1fgetc 与 fputc
fgetc函数从指定的文件中读一个字节,getchar从标准输入读一个字节,调用getchar()相当于调用fgetc(stdin)。
int fgetc(FILE *stream);
int getchar(void);
返回值:成功返回读到的字节,出错或者读到文件末尾时返回EOF
fputc函数向指定的文件写一个字节,putchar向标准输出写一个字节,调用putchar(c)相当于调用fputc(c, stdout)。
int fputc(int c, FILE *stream);
int putchar(int c);
返回值:成功返回写入的字节,出错返回EOF
#includeusing namespace std;int main(){ FILE *fp= fopen("c:\\log.txt","r"); if(fp==NULL){ cout<<"can't open the file log.txt !!"< <<"can't write the file log.txt !!"< <<"can't write to the file !"< <<"write successfully!!"<
2 fgets 和 fputs
fgets从指定的文件中读一行字符到调用者提供的缓冲区中,gets从标准输入读一行字符到调用者提供的缓冲区中
char *fgets(char *s, int size, FILE *stream);//参数s是缓冲区的首地址,size是缓冲区的长度,该函数从stream所指的文件中读取以'\n'结尾的一行(包括'\n'在内)存到缓冲区s中,并且在该行末尾添加一个'\0'组成完整的字符串
char *gets(char *s);
返回值:成功时s指向哪返回的指针就指向哪,出错或者读到文件末尾时返回NULL
如果文件中的一行太长,fgets从文件中读了size-1个字符还没有读到'\n',就把已经读到的size-1个字符和一个'\0'字符存入缓冲区,文件中剩下的半行可以在下次调用fgets时继续读。如果一次fgets调用在读入若干个字符后到达文件末尾,则将已读到的字符串加上'\0'存入缓冲区并返回,如果再次调用fgets则返回NULL,可以据此判断是否读到文件末尾。
fgets只适合读文本文件而不适合读二进制文件,并且文本文件中的所有字符都应该是可见字符,不能有'\0'。
int fputs(const char *s, FILE *stream);
int puts(const char *s);
返回值:成功返回一个非负整数,出错返回EOF
缓冲区s中保存的是以'\0'结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的'\0'。与fgets不同的是,fputs并不关心的字符串中的'\n'字符,字符串中可以有'\n'也可以没有'\n'。puts将字符串s写到标准输出(不包括结尾的'\0'),然后自动写一个'\n'到标准输出
#includeusing namespace std;int main(){ FILE *fp= fopen("c:\\log.txt","r"); if(fp==NULL){ cout<<"can't open the file log.txt !!"<
3 fscanf和fprintf函数
fprintf函数和fscanf函数和printf和scanf相比,就是多了个f前缀,这个f当然就是指的file,也就是文件了,后两者是操作的对象是终端设备,前者则是针对磁盘文件的操作,因此fprintf函数和fscanf函数就是了C语言中文件的格式化输入输出函数。
fprintf(文件结构指针,格式字符串,输出表列);
fscanf(文件结构指针,格式字符串,输出表列);
#includeusing namespace std;struct student{ char chName[20]; //姓名 int nID; //学号 float fScores[3]; //3门课的成绩};int main(){ FILE *pWrite,*pRead; struct student tStu,tStu2; char *pName = "letuknowit"; pWrite=fopen("stu_scores.txt","w"); if(NULL == pWrite) { exit(1); } //初始化结构体信息,用于写入文件 memcpy(tStu.chName,pName,20); tStu.nID = 1; tStu.fScores[0] = 89.0; tStu.fScores[1] = 87.0; tStu.fScores[2] = 88.0; //写入数据到文件中 fprintf(pWrite,"%d %s %f %f %f\n",tStu.nID,tStu.chName,tStu.fScores[0],tStu.fScores[1],tStu.fScores[2]); fprintf(pWrite,"%d %s %f %f %f\n",tStu.nID,tStu.chName,tStu.fScores[0],tStu.fScores[1],tStu.fScores[2]); fclose(pWrite); pRead=fopen("stu_scores.txt","r"); if(NULL == pRead) { exit(1); } while(!feof(pRead)){//没有达到文件末尾 //从文件中读取数据(主要下面参数中的&) fscanf(pRead,"%d %s %f %f %f\n",&tStu2.nID,tStu2.chName,&tStu2.fScores[0],&tStu2.fScores[1],&tStu2.fScores[2]); printf("%d %s %.1f %.1f %.1f\n",tStu2.nID,tStu2.chName,tStu2.fScores[0],tStu2.fScores[1],tStu2.fScores[2]); } fclose(pRead); system("pause"); return 0;}
随机文件的操作
1 fread与fwrite函数
参考:
用来读写一个数据块
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
(1)buffer:是一个指针,对fread来说,它是读入数据的存放地址。对fwrite来说,是要输出数据的地址。
(2)size:要读写的字节数;
(3)count:要进行读写多少个size字节的数据项;
(4)fp:文件型指针。
1 完成次写操(fwrite())作后必须关闭流(fclose());
2 完成一次读操作(fread())后,如果没有关闭流(fclose()),则指针(FILE * fp)自动向后移动前一次读写的长度,不关闭流继续下一次读操作则接着上次的输出继续输出;
如
fread(f,4,2,fp);
f是一个实行数组的名称,一个int型变量占四个字节,这个函数从fp指向的文件读入两次(每次四个字节)存入数组f中
#includeusing namespace std;int main(){ int a=123456789; FILE* fp; fp=fopen("a.txt","wb+"); if(fp==0){ puts("error"); exit(0); } fwrite(&a,sizeof(int),1,fp); fwrite(&a,sizeof(int),1,stdout); fclose(fp); system("pause"); return 0;}
fwrite只输出二进制流,忠实的输出给它的数据。在例子里,给fwrite的是4个字节,fwrite就忠实地把这四个字节分别写到了文件、标准输出里。
2 文件定位函数
文件的随机读写就是可以将文件指针直接定位在所要求读写的位置而不必从文件头开始直到要求的位置再进行读写
rewind函数:使位置指针重新返回到文件的开头,没有返回值。rewind(文件指针)
fseek函数:讲文件指针移动到指定的位置上。fseek(文件指针,偏移量,起始点); 偏移量以起始点为基准向文件末尾移动的总字节数。起始点可以使文件开始,文件当前位置,文件末尾
SEEK_SET: 文件开头, 0
SEEK_CUR: 当前位置, 1
SEEK_END: 文件结尾, 2
fseek(fp,100,0);把文件内部指针移动到离文件开头100字节处;
fseek(fp,100,1);把文件内部指针移动到离文件当前位置100字节处;
fseek(fp,-100,2);把文件内部指针退回到离文件结尾100字节处。
ftell函数:返回文件指针的当前读写位置,这个位置是用相对文件起始位置的字节偏移量来表示的
c++流
打开文件
void open(const unsigned char *filename,int mode,int access);
access
0 一般文件
1 只读文件
2 隐藏文件
3 系统文件
打开方式
在实际使用过程中,可根据需要将以上打开文件的方式用“|”组合起来。如:
ios::in|ios::out表示以读/写方式打开文件
ios::in|ios::binary表示以二进制读方式打开文件
ios::out|ios::binary表示以二进制写方式打开文件
ios::in|ios::out|ios::binary表示以二进制读/写方式打开文件
如果未指明以二进制方式打开文件,则默认是以文本方式打开文件。
关闭文件
在文件操作结束时应及时调用成员函数close()来关闭文件。如:要关闭的文件对象名为myfile,则可使用如下语句关闭文件:
myfile.close();
文件读写
在打开文件后就可以对文件进行读写操作了。从一个文件中读出数据,可以使用iostream类的get、getline、read成员函数以及运算符“>>”;而向一个文件写入数据,可以使用其put、write函数以及插入符“<<”。
#include#include using namespace std;int main(){ fstream myfile; myfile.open("f1.txt",ios::out); if(!myfile){ cout<<"can't open the file!!"< <<20< <<"file write testing!!!"< <<"can't open the file!!"< < <
随机访问文件
#include#include using namespace std;struct student{ char name[20]; char num[10]; float score; };int main(){ student stu[3]={ {"wang","19",25},{"li","20",76},{"xu","23",91}}; student s; fstream f1; f1.open("student.txt",ios::out|ios::in|ios::binary);//以读写方式打开二进制文件 if(!f1){ cout<<"can't open the file!!"< < 3; i++){ f1.write((char*)&stu[i], sizeof(student)); } f1.seekp(sizeof(student)*2);//将指针定位到第三位同学 f1.read((char*)&s,sizeof(student));//读取第三位同学的数据 cout< <<" "< <<" "< <