C++ 文件操作

打开文件的方式:
fopen:
   函数原型:FILE * fopen(const char * path,const char * mode);
   返回值:文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno中。
   一般而言,打开文件后会做一些文件读取或写入的动作,若打开文件失败,接下来的读写动作也无法顺利进行,所以一般在fopen()后作错误判断及处理。
示例:
    FILE*fp=NULL;//需要注意
    fp=fopen(F_PATH,"r");


fopen_s:
   函数原型:errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );
   函数参数:pFile 文件指针将接收到打开的文件指针指向的指针。infilename 文件名。inmode 允许的访问类型。
   返回值:如果成功返回0,失败则返回相应的错误代码。
示例:
   FILE*fp;
   errno_t err;
   err=fopen_S(&fp,F_path,"a");
   if(err!=0)
    {
      //判断文件是否打开
    }


使用ifstream打开文件进行读取:
   如果一个文件名被申明为“string”,那么就必须使用 “c_str”,然而,当你申明一个文件名为字符数组型,就没有必要使用,比如。 


   ifstream infile
   char filename[m];
   infile.open(filename,ios::in);//ios::in ios::out ios::binary  ios::app ios::ate(初始位置 文件尾) ios::trunc
   infile.clear();


   string filename;
   infile.open(filename.c_str,ios::in);
   infile.clear();


使用ofstream打开文件进行写入:
   ofstream outfile;
   char filename;
   outfile.open(filename,ios::out);
   outfile.close();//根据实验,如果不关闭文件,就去打开下一个文件,则会导致编译通过,但运行后,两个文件都没有内容。当关闭后再打开就正常了 
   outfile.clear();
!!!注:
   1 尽量不要重用文件流对象。以防自己或他人查错时因为编译通过,执行不对,无法定位错误。并不是每个人都清楚infile对象的细节。 
   2 如果重用infile文件流对象,必须在打开新文件之前,调用infile.close()和infile.clear().  
     不调用infile.close()关闭前一个文件就去打开新文件,会导致前一个文件破坏,因为infile关联的是前一个文件。千万得注意,文件改了就不能回复了,除非你有备份。 
     不调用infile.clear()将使得 读取文件失败。因为对象流虽然挂接到新文件但属性状态没有改变。——close() 并不清除状态。 




关闭文件方式:
   fclose是一个函数名,功能是关闭一个流。注意:使用fclose()函数就可以把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区。
   函数原型:int fclose( FILE *fp );
   返回值:如果流成功关闭,fclose 返回 0,否则返回EOF(-1)。
示例:
   FILE *fp = NULL;
   fp = fopen("DUMMY.FIL","w");/*创建一个包含10个字节的文件*/
   fwrite(buf,strlen(buf),1,fp);/*将buf内容写入到文件中*/
   fclose(fp);/*关闭文件*/
   fp = NULL;




对文件进行读&&写操作:

读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式

1、文本文件的读写 
文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:

file2<<"I Love You";//向文件写入字符串"I Love You"
int i;
file1>>i;//从文件输入一个整数值。
这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些

操纵符 功能 输入/输出 
dec 格式化为十进制数值数据 输入和输出 
endl 输出一个换行符并刷新此流 输出 
ends 输出一个空字符 输出 
hex 格式化为十六进制数值数据 输入和输出 
oct 格式化为八进制数值数据 输入和输出 
setpxecision(int p) 设置浮点数的精度位数 输出

比如要把123当作十六进制输出:file1<<hex<<123;要把3.1415926以5位精度输出:file1<<setpxecision(5)<<3.1415926。

2、二进制文件的读写 
①put() 
put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。

②get() 
get()函数比较灵活,有3种常用的重载形式:

      一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。
     另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。
      还 有一种形式的原型是:ifstream &get(char *buf,int num,char delim='n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符'n'。例如:
file2.get(str1,127,'A');//从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。

③读写数据块 
要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:

read(unsigned char *buf,int num);
write(const unsigned char *buf,int num);
read() 从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。
例:
unsigned char str1[]="I Love You";
int n[5];
ifstream in("xxx.xxx");
ofstream out("yyy.yyy");
out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
in.close();out.close();
四、检测EOF 
成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
例:
if(in.eof())ShowMessage("已经到达文件尾!");
五、文件定位 
和 C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时, 相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是 seekg()和 seekp(),seekg()是设置读位置,seekp是设置写位置。它们最通用的形式如下:
istream &seekg(streamoff offset,seek_dir origin);
ostream &seekp(streamoff offset,seek_dir origin);
streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:

ios::beg: 文件开头 
ios::cur: 文件当前位置 
ios::end: 文件结尾 
这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。
例:
file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节
file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节


有关cin的用法:


  1、cin
  2、cin.get()
  3、cin.getline()
  4、getline()
  5、gets()
  6、getchar()


  1、cin>>


 用法1:最基本,也是最常用的用法,输入一个数字:


  #include <iostream>
  using namespace std;
  main ()
  {
  int a,b;
  cin>>a>>b;
  cout<<a+b<<endl;
  }
  输入:2[回车]3[回车]
  输出:5
  用法2:接受一个字符串,遇“空格”、“TAB”、“回车”都结束
  #include <iostream>
  using namespace std;
  main ()
  {
  char a[20];
  cin>>a;
  cout<<a<<endl;
  }
  输入:jkljkljkl
  输出:jkljkljkl
  输入:jkljkl jkljkl //遇空格结束
  输出:jkljkl
  2、cin.get()
 用法1: cin.get(字符变量名)可以用来接收字符
  #include <iostream>
  using namespace std;
  main ()
  {
  char ch;
  ch=cin.get(); //或者cin.get(ch);
  cout<<ch<<endl;
  }
  输入:jljkljkl
   输出:j
 用法2:cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格
  #include <iostream>
  using namespace std;
  main ()
  {
  char a[20];
  cin.get(a,20);
  cout<<a<<endl;
  }
  输入:jkl jkl jkl
  输出:jkl jkl jkl
  输入:abcdeabcdeabcdeabcdeabcde (输入25个字符)
  输出:abcdeabcdeabcdeabcd (接收19个字符+1个'\0')
  用法3:cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符,或者舍弃回车,弥补cin.get(字符数组名,接收字符数目)的不足.
  这个我还不知道怎么用,知道的前辈请赐教;
  3、cin.getline() // 接受一个字符串,可以接收空格并输出,存入为一个数组
  #include <iostream>
  using namespace std;
  main ()
  {
  char m[20];
  cin.getline(m,5);
  cout<<m<<endl;
  }
  输入:jkljkljkl
  输出:jklj
    接受5个字符到m中,其中最后一个为'\0',所以只看到4个字符输出;
  如果把5改成20:
  输入:jkljkljkl
  输出:jkljkljkl
  输入:jklf fjlsjf fjsdklf
  输出:jklf fjlsjf fjsdklf
  //延伸:
  //cin.getline()实际上有三个参数,cin.getline(接受字符串的数组空间m,接受个数5,结束字符)
  //当第三个参数省略时,系统默认为'\0'
  //如果将例子中cin.getline()改为cin.getline(m,5,'a');当输入jlkjkljkl时输出jlkj,输入jkaljkljkl时,输出jk
  当用在多维数组中的时候,也可以用cin.getline(m[i],20)之类的用法:
  #include<iostream>
  #include<string>
  using namespace std;
  main ()
  {
  char m[3][20];
  for(int i=0;i<3;i++)
  {
  cout<<"\n请输入第"<<i+1<<"个字符串:"<<endl;
  cin.getline(m[i],20);
  }
  cout<<endl;
  for(int j=0;j<3;j++)
  cout<<"输出m["<<j<<"]的值:"<<m[j]<<endl;
  }
  请输入第1个字符串:
  kskr1
  请输入第2个字符串:
  kskr2
  请输入第3个字符串:
  kskr3
  输出m[0]的值:kskr1
  输出m[1]的值:kskr2
  输出m[2]的值:kskr3
  4、getline() // 接受一个字符串,可以接收空格并输出,存入空间为字符串地址,需包含“#include<string>”
  #include<iostream>
  #include<string>
  using namespace std;
  main ()
  {
  string str;
  getline(cin,str);
  cout<<str<<endl;
  }
  输入:jkljkljkl
  输出:jkljkljkl
  输入:jkl jfksldfj jklsjfl
  输出:jkl jfksldfj jklsjfl
  和cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数
  5、gets() // 接受一个字符串,可以接收空格并输出,需包含“#include<string>”
  #include<iostream>
  #include<string>
  using namespace std;
  main ()
  {
  char m[20];
  gets(m); //不能写成m=gets();
  cout<<m<<endl;
  }
  输入:jkljkljkl
  输出:jkljkljkl
  输入:jkl jkl jkl
  输出:jkl jkl jkl
  类似cin.getline()里面的一个例子,gets()同样可以用在多维数组里面:
  #include<iostream>
  #include<string>
  using namespace std;
  main ()
  {
  char m[3][20];
  for(int i=0;i<3;i++)
  {
  cout<<"\n请输入第"<<i+1<<"个字符串:"<<endl;
  gets(m[i]);
  }
  cout<<endl;
  for(int j=0;j<3;j++)
  cout<<"输出m["<<j<<"]的值:"<<m[j]<<endl;
  }
 请输入第1个字符串:
  kskr1
  请输入第2个字符串:
  kskr2
  请输入第3个字符串:
  kskr3
  输出m[0]的值:kskr1
  输出m[1]的值:kskr2
  输出m[2]的值:kskr3
  自我感觉gets()和cin.getline()的用法很类似,只不过cin.getline()多一个参数罢了;
  这里顺带说明一下,对于本文中的这个kskr1,kskr2,kskr3的例子,对于cin>>也可以适用,原因是这里输入的没有空格,如果输入了空格,比如“ks kr jkl[回车]”那么cin就会已经接收到3个字符串,“ks,kr,jkl”;再如“kskr 1[回车]kskr 2[回车]”,那么则接收“kskr,1,kskr”;这不是我们所要的结果!而cin.getline()和gets()因为可以接收空格,所以不会产生这个错误;
  6、getchar() //接受一个字符,需包含“#include<string>”


  #include<iostream>
  #include<string>
  using namespace std;
  main ()
  {
  char ch;
  ch=getchar(); //不能写成getchar(ch);
  cout<<ch<<endl;
  }
  输入:jkljkljkl
  输出:j
  //getchar()是C语言的函数,C++也可以兼容,但是尽量不用或少用


fread()与read()的区别:


   fread()函数原型:size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
   参 数:buffer 用于接收数据的内存地址;size 要读的每个数据项的字节数,单位是字节;count 要读count个数据项,每个数据项size个字节;stream  输入流。
   fread是一个函数。从一个文件流中读数据,最多读取count个项,每个项size个字节,如果调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回 0。
   C语言示例:
   
#include<stdio.h>
#include<string.h>
int main(void)
{
    FILE*stream;
    char msg[]="this is a test";
    char buf[20];
    if((stream=fopen("DUMMY.FIL","w+"))==NULL)
    {
        fprintf(stderr,"Can not open output file.\n");
        return 0;
    }
    /*write some data to the file*/
    fwrite(msg,1,strlen(msg)+1,stream);
    /*sizeof(char)=1 seek to the beginning of the file*/
    fseek(stream,0,SEEK_SET);
    /*read the data and display it*/
    fread(buf,1,strlen(msg)+1,stream);
    printf("%s\n",buf);
    fclose(stream);
    return 0;
}




   Linux C  read()函数原型:ssize_t read[1]  (int fd, void *buf, size_t count);
   参数:count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1。注意返回值类型是ssize_t,表示有符号的size_t,这样既可以返回正的字节数、0(表示到达文件末尾)也可以返回负值-1(表示出错)。
   read函数返回时,返回值说明了buf中前多少个字节是刚读上来的。有些情况下,实际读到的字节数(返回值)会小于请求读的字节数count,例如:读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0。
   示例:
#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{
    void* buf ;
    int handle;
    int bytes ;
    buf=malloc(10);
    /*
    Looks for a file in the current directory named TEST.$$$ and attempts
    to read 10 bytes from it.To use this example you should create the
    file TEST.$$$
    */
    handle=open("TEST.$$$",O_RDONLY|O_BINARY,S_IWRITE|S_IREAD);//open是UNIX系统(包括LINUX、Mac等)的系统调用函数,区别于C语言库函数fopen。返回值:成功则返回文件描述符,否则返回-1
    if(handle==-1)
    {
        printf("ErrorOpeningFile\n");
        exit(1);
    }
    bytes=read(handle,buf,10);
    if(bytes==-1)
    {
        printf("ReadFailed.\n");
        exit(1);
    }
    else 
    {
        printf("Read:%dbytesread.\n",bytes);
    }
    return0 ;
}


fwrite()的用法:
   size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
   注意:这个函数以二进制形式对文件进行操作,不局限于文本文件
   返回值:返回实际写入的数据块数目
   (1)buffer:是一个指针,对fwrite来说,是要获取数据的地址;
   (2)size:要写入内容的单字节数;
   (3)count:要进行写入size字节的数据项的个数;
   (4)stream:目标文件指针;
   (5)返回实际写入的数据项个数count。
示例:
#include <stdio.h>
struct mystruct
{
    int i;
    char cha;
};
int main(void)
{
    FILE *stream;
    struct mystruct s;
    if ((stream = fopen("TEST.$$$", "wb")) == NULL) /* open file TEST.$$$ */
    {
        fprintf(stderr, "Cannot open output file.\n");
        return 1;
    }
    s.i = 0;
    s.cha = 'A';
    fwrite(&s, sizeof(s), 1, stream); /* 写的struct文件*/
    fclose(stream); /*关闭文件*/
    return 0;
}










































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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值