文件操作

打开和关闭文件
要执行文件的输入输出,须做以下几件事:
(1) 在程序中包含头文件fstream;
(2) 建立文件流。建立文件流的过程就是定义流类的对象,例如:
ifstream in;
ofstream out;
fstream both;
分别定义了输入流对象in;输出流对象out,输入输出流对象both。
(3) 使用open()函数打开文件,也就是使某一文件与上面的某一流相联系。open()函数是上述三个流类的成员函数,其原型是在fstream.h中定义的, 原型为:
void open(const unsigned char*,int mode,int access=filebuf::openprot);
(4) 对open结果进行检查(检查打开操作是否成功。可省略,但不推荐。)
(5)进行读写。在建立(或打开)的文件上执行所要求的输入或输出操作;
(6)关闭文件流对象。

文件读写的例子

#include 
using namespace std;
int main(){
    ofstream  fout;
     fout.open("f:\\test.txt",ios::out);//建立文件信息区 
      if (! fout.is_open()){   cout<<"Cannot open output file\n,"; return 1;}
      fout<<10<<"  "<<123.456<<"  "<<"This is a text file.\n";
      fout.close();
      return 0;
} 

a.is_open()函数, 该函数用来判断文件打开是否成功(建立文件信息区)。
也可以通过判断流的状态 if(fout.fail()): if(! fout.good())
还可以采用:if(! fout):测定 对象 a 是否 建立/存在(fstream 类对象不能使用这种方式)

#include
using namespace std;
int main(){
    ofstream  fout;char filename[20];cin>>filename;
     fout.open(filename,ios::out);//建立文件信息区 
      if (! fout.is_open()){   cout<<"Cannot open output file\n,"; return 1;}
      fout<<10<<"  "<<123.456<<"  "<<"This is a text file.\n";
      fout.close();
      return 0;
} 
#include
#include  
using namespace std;
int main(){
    ofstream  fout;string filename;cin>>filename;
     fout.open(filename.c_str(),ios::out);//建立文件信息区 
      if (! fout.is_open()){   cout<<"Cannot open output file\n,"; return 1;}
      fout<<10<<"  "<<123.456<<"  "<<"This is a text file.\n";
      fout.close();
      return 0;
} 

void open(const unsigned char*,int mode,int access=filebuf::openprot);
const unsigned char*:文件名,为无符号的常字符,即常字符串。若输入为字符串对象,必须将该字符对象转换为C语言风格,即将字符串对象转换为字符数组。

文件打开
open()函数原型在fstream中定义,函数原型如下:
void open (char* filename, int mode, int access=0);

第一个参数用于传递文件名;

第二个参数mode值表示文件的使用方式;

第三个参数打开文件的共享方式
filebuf::openprot; //默认的兼容共享方式(与MS_DOS文件兼容)
filebuf::sh_none;  //独占,不共享
filebuf::sh_read;  //读共享
filebuf::sh_write; //写共享

文件打开方式
ios::in  = 0x01,//供读, (ifstream默认的打开方式)
ios::out  = 0x02, //供写,文件不存在则创建,若文件已存在则清空原内容(ofstream默认的打开方式)
ios::ate  = 0x04, //文件打开时,指针在文件尾部。可改变指针的位置,常和in、out联合使用
ios::app    = 0x08, //供写,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,指针位置总在最后
ios::trunc   = 0x10, //在读写前先将文件长度截断为0(默认)
ios::binary  = 0x80  //二进制格式文件

ios::in: 用于输入。文件以输入方式打开

  • ifstream流类的默认打开方式
  • 文件存在,打开文件;
  • 文件不存在,打开失败。

ios::out: 用于输出。文件以输出方式打开。

  • ofstream流类的默认打开方式
  • 如果文件存在,打开文件,并清空原文件中的内容。
  • 如果文件不存在,则创建文件。
  • 如果文件路径错误,创建流对象操作失败。

ios::app: 以追加的方式打开文件。主要用于文件的写操作。如果文件不存在,则创建文件。如果文件存在,则不会删除文件中的内容

  • 在该模式下,不管文件指针处于何处,新写入的内容永远在文件尾。
int main(){
 fstream f;
 f.open("result.txt",ios::app);
 f.put('d');
       f.seekp(ios::beg);//移动文件写指针到文件开始
       f.put(‘e’); //文件写操作仍在文件尾部
 return 0;
}

ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性。

  • 以out方式打开文件时
  • 如果文件不存在,创建文件,
  • 如果文件存在,则会删除原来的文件
  • 以in 方式打开文件时
  • 如果文件不存在,打开失败
int main()
{
 fstream f;
 f.open("result1.txt",ios::ate|ios::in);
 if(!f)
  cout<<"Error!";
 return 0;
}

文件操作_第1张图片

关闭文件
关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接。若流对象的生存期没有结束,可以重用 ,当一个流对象的生存期结束,系统也会自动关闭文件 。

ofstream ofile ; //创建输入文件流
ofile . open ( “myfile1” ) ; //ofile流与文件“myfile1”相关联
… //访问文件“myfile1”
ofile . close ( ) ; //关闭文件“myfile1”
ofile . open ( “myfile2” ); //重用ofile流

#include
#include
using namespace std;
int main ( ){
   ofstream  ost ;   
   ost . open ( "d:\\my1.dat ") ;
   ost << 20 << endl ; 
   ost << 30.5 << endl ;
   ost . close ( ) ;  
   ifstream  ist ( "d:\\my1.dat" ) ; 
   int  n ;
   double  d ;
   ist >> n >> d ;  
   cout << n << endl << d << endl ;
}

文件操作_第2张图片
文件操作_第3张图片

文本文件

文本文件用默认方式打开

文本文件用文件流对象(文本文件流)进行读/写操作

文本文件是顺序存取文件

通常一个逻辑记录用换行符分隔;数据项之间可以用空白符、换行符、制表符等分隔
文件中只存储了数据,没有存储记录的逻辑结构
每条记录的长度是不同的
只能顺序访问每一条记录

//把一个整数、一个浮点数和一个串写到文件 d:\test 中
#include
#include
using namespace std;
int main(){
   ofstream out( "d:\\test" ) ;
   if ( !out )
      {return 0;  }
   out << 10 << " " << 123.45 << " " ;
   out << "\nThis is a short text file." ;
   out.close () ;
   return 1 ;
}

文件操作_第4张图片

//从文件 d:\test 中读出一个整数、一个浮点数、一个字符和两个串
#include
#include < fstream >
using namespace std;
int main (){
   char ch ;
   int  i ;
   float  f ;
   char  str1 [ 10 ] ,   str2 [ 10 ] ;
   ifstream  in ( "d:\\test" ) ;
   if  ( ! in ) {return 0 ; }
   in >> i >> f >> ch >> str1 >> str2 ;
   cout << i << " " << f << " " << ch << '\n' ;
   cout << str1 << str2 << endl ;
   in.close () ;
}

文件操作_第5张图片

//把文件 d:\test 复制到文件 d:\testnew 中
#include
#include 
using namespace std;
int main ( ){ 
   char  ch ;
   ifstream  f1 ( "d:\\test" ) ;
   if  ( !f1 )    {return 0;  }
   ofstream  f2 ( "d:\\testnew" ) ;
   if  ( !f2 )   {return 0;  }
   while ( f1 && f1.get(ch) )   f2.put( ch ) ;
   f1.close () ;
   f2.close () ;
   cout << "It is over !\n" ;
}
//建立一个包含学生学号、姓名、成绩的文本文件
#include
#include 
using namespace std;
int main(){ 
   char fileName[30];
   string name;     
   int number , score ;
   ofstream outstuf ; 
    cin >> fileName ; 
   outstuf.open( fileName, ios::out ) ;
   if ( !outstuf )
     { cerr << "File could not be open." << endl ;    abort();  }
outstuf << "学生成绩文件\n" ;
     while( cin >> number >> name >> score )     {
         outstuf << number << ' ' << name << ' ' << score << '\n' ;    
         cout << "? " ;
    }  
   outstuf.close() ;
}
//读文本文件。在屏幕显示学生记录,以及最高分数、最低分数和平均分数 
#include
#include 
using namespace std;
int main(){
   string name , s ;   
   int number , score ;   int n = 0, max, min, total = 0 ;  double ave;
   ifstream instuf( "d:\\students.txt", ios::in ) ;
   if ( !instuf )
      {abort();   }
   instuf.getline( s, 80 ) ;
while( instuf >> number >> name >> score )     {
        cout << number << '\t' << name << '\t' << score << '\n' ; 
        if (n==0) { max = min = score; }
  else
   {
     if ( score > max ) max = score ;   
     if ( score < min ) min = score ; } 
        total+=score;      n++;
     }
     ave = double(total) / n ;
     cout << max << endl << min << endl
   << ave << endl; 
    instuf.close() ;
}
//利用类对文件操作进行封装,实现学生信息文件内容的显示,文件中添加记录等基本的操作
#include 
#include
#include 
using namespace std;
struct student{
 string  name ;
 int number , score ;
};
class FileOperation{
 string filename;
 student record[100]; //假设文件中存储的及记录个数不超过100
 int num;//存储记录的个数
public:
 FileOperation();
 void display(); 
 void append();
   ~FileOperation();
};
FileOperation::FileOperation(){
 cin>>filename;
 ifstream instuf( filename.c_str(), ios::in ) ;
 num=0;
 if ( !instuf )
 {exit(0);   }
 instuf >> record[num].number >> record[num].name >> record[num].score;
 while(!instuf.eof() )      {
  num++;
  instuf >> record[num].number >> record[num].name >> record[num].score;
 }
 instuf.close();
}
void FileOperation::display()
{
 cout<<"number"<<"\t"<<"name"<<"\t"<<"score"<<endl;
 for(int i=0;i<num;i++)
  cout << record[i].number << '\t' << record[i].name << '\t' << record[i].score << '\n' ; 
}
void FileOperation::append()
{
 cin>>record[num].number>>record[num].name>>record[num].score;
 num++;
}
FileOperation::~FileOperation(){
 ofstream outstuf ; 
 outstuf.open( filename.c_str(), ios::out ) ;
 if ( !outstuf ) 
    abort();  
 for(int i=0;i<num;i++)  
    outstuf << record[i].number << ' ' << record[i].name << ' ' << record[i].score << '\n' ;    
   outstuf.close() ;
}
int main()
{
 FileOperation f;
 f.append();
 f.display();
 return 0;
}

二进制文件
二进制文件以基本类型数据在内存的二进制表示形式存放数据,不对写入或读出的数据做格式转换 ==
二进制文件的读写方式由程序控制
== 打开二进制文件用binary方式

==二进制文件是随机存取文件 ==

二进制文件是顺序存取文件

文件中只存储了数据,没有存储记录的逻辑结构
每条记录的长度是相同的
可以随机访问每一条记录

用read()函数和write()函数读写文件 (成块的读写)
可以成块(若干字节)进行读写操作
读写的过程中不进行转换(不存在二进制流到文本流得转换)
适用于二进制文件。

read()和write()原型如下:
istream &read(unsigned char* buf,int num);
ostream &write(const unsigned char* buf,int num);

//用write()函数向文件test中写入整数与双精度数。
#include
int main(){
    ofstream  out(“f:\\test.dat”,ios::binary);
     if (!out) {return 1; }
     int i=12340; double num=100.45;
     out.write((char *) &i,sizeof(int));
     out.write((char *) &num,sizeof(double));
     out.close();
    ifstream in("f:\\test.dat");
     if (!in)  {return 1; }
     int j;double d; 
     in.read((char *)&j,sizeof(int));
     in.read((char *)&d,sizeof(double));
     cout<<j<<" "<<d<<endl;
     in.close();
     return 0; 
} 
//从键盘输入若干个学生的有关数据,然后把它们转存到磁盘文件上去。 
#include 
#include 
using namespace std;
class Student{
 char name[10];
 int num;
 int age;
 char addr[20];
          public:
 friend ostream & operator <<(ostream &out,Student &obj){
                 out<<obj.name<<"\t"<<obj.num<<"\t"<<obj.age<<"\t"<<obj.addr<<endl;
  return out;
 }
 friend istream& operator >>(istream & in,Student obj) {
  in>>obj.name>>obj.num>>obj.age>>obj.addr;
  return in; 
               }
}; 
class Student_list{
 Student stud[1000]; 
 int number;
         public:
 Student_list();
 void input();
 void display() ;
 ~Student_list();
};
Student_list::Student_list(){
 fstream fin("stu.dat",ios::in|ios::binary);
 int i=0;
 number=i;
 if(!fin) return ;
 fin.read ((char *)&stud[i],sizeof(Student));   
 while(!fin.eof()){
  i++;
  fin.read ((char *)&stud[i],sizeof(Student));   
 }
 number=i;
   fin.close ();
   return ;
}
void Student_list::input()
{
 cin>>stud[number++];
}
void Student_list::display()
{
 for (int i=0;i<number; i++)
  cout<<stud[i];
 return ;
}
Student_list::~Student_list()
{
 fstream fout("stu.dat",ios::out|ios::binary);
 if(!fout)      
 {
  cout<<"cannot open file\n";
  return;
 }
 for(int i=0;i<number;i++)
  fout.write((char *)&stud[i],sizeof(Student));
           //fout.write((char *) stud, number*sizeof(Student));
    fout.close();
}
int main()
{
 Student_list s_list;
 while(1)
 {
  s_list.input();
  cout<<"Continue(Y/N)?";
  char ch;
  cin>>ch;
  if(ch=='N' || ch=='n')
   break;
 }
 s_list.display();
 return 0;
}

fin.read(内存地址 char,字节数);*
注意:这里的char需要做类型转换,reinterpret_cast>(…);
fout.write(内存地址 char,字节数);*
在c语言中,fread(内存地址,单位大小,总个数,文件)和fwrite是将数据在文件和内存中间移动处理,对应c++的为fin.read(内存地址 注意这里需要强制性类型转换,字节数)和fout.write(内存地址,字节数)。
fin.getcount() 最后一次read操作读到几个字节

bool eof();
如果达到相关联的文件末尾,eof()函数返回true,否则返回false

文件的随机读写
在C++的I/O系统中有个文件指针,它有两个名字。
其中一个名字叫get指针,用于指出下一次输入操作的位置;
另一个名字叫做put指针,用于指出下一次输出操作的位置。

istream 类操作流读指针的成员函数
istream & istream :: seekg ( long pos) ;
作用:读指针从流的起始位置向后移动由pos指定字节
istream & istream :: seekg ( long off, ios::seek_dir ) ;
作用:读指针从流的seek_dir位置移动 off 指定字节
ios::seek_dir 值:
cur 相对于当前读指针所指定的当前位置
beg 相对于流的开始位置
end 相对于流的结尾处
enum ios::seek_dir { beg = 0 ; cur = 1 , end = 2 } ;

istream & istream :: tellg () ;
作用:返回读指针当前所指位置值

put指针的操作:
ostream& seekp(streampos pos); //移动put指针到 pos位置
ostream& seekp(streamoff offset ,ios::seek_dir dir);
long tellp(); //获取 put 指针的值
其中,参数dir表示文件指针的起始位置,off表示相对于这个起始位置的位移量。dir的取值有以下3种情况:
①ios::beg 从文件头开始,文件指针移动由off指定的距离。
②ios::cur 从当前位置开始,文件指针移动由off指定的距离。
③ios::end 从文件尾开始,文件指针移动由off指定的距离。
例:datafile.seekp(-20L,ios::cur); //表示将文件定位指针从当前位置向文件头部方向移20个字节。

#include 
void main()    {
   // 假如我们已经在test_file.txt中存有了“Hello”的内容
   ifstream File("test_file.txt");
   char arr[10];
   File.read(arr,10);
   // 由于Hello占5个字符,因此这里将返回5
   cout << File.tellg() << endl; 
   File.close();
}

get指针的操作:
istream& seekg(streampos pos); //指针直接定位
istream& seekg(streamoff off,ios::seek_dir dir); //指针相对定位
long tellg();// 获取get指针的值
其中,参数dir表示文件指针的起始位置,off表示相对于这个起始位置的位移量。dir的取值有以下3种情况:
①ios::beg 从文件头开始,文件指针移动由off指定的距离。
②ios::cur 从当前位置开始,文件指针移动由off指定的距离。
③ios::end 从文件尾开始,文件指针移动由off指定的距离。
例:datafile.seekg(-20L,ios::cur); //表示将文件定位指针从当前位置向文件头部方向移20个字节。

//将文件test中第五个字符修改成X 。
#include
#include
void main(void){
    fstream fs;
    fs.open("d:\\test",ios::in| ios::out); // 以读写方式打开文件
    if (fs.fail())
         cout<<"open file errer!";
    else {
          fs.seekp(4,ios::beg);   // 设置写指针
          fs.put('X');
          char contents[10];
          fs.seekg(0,ios::beg);   // 设置读指针
          fs.get(contents,10);
          cout<<contents;
    }
    fs.close();
} 

命令行参数
C++程序的main函数可以添加参数,即main函数的原型为:
int main(int argc, char* argv[]);
argc:接受字符串的个数
argv:接受程序作为命令行执行时输入的字符串

例如,若exe文件名为testmain,在命令窗口输入:
testmain aaa bbb ccc
则有: argv[0] 为 “testmain”
argv[1] 为 “aaa”
argv[2] 为 “bbb”
argv[3] 为 “ccc”
argc 为 4

//建立一个Win32控制台程序,生成exe文件名为testmain.exe,
//放到D:\盘上,用命令行方式执行
#include
using namespace std;
int main(int argc, char* argv[])
{   
    int i; 
    cout<<"argc="<<argc<<endl;
    for(i=0; i<argc; i++)
         cout<<argv[i]<<endl;
    return 0;
}

文件操作_第6张图片

你可能感兴趣的:(文件操作)