李sir_Blog

博客园 首页 联系 订阅 管理

一.输出文件流成员函数

1.输出流的open函数
    要使用一个输出文件流(ofstream),必须在构造函数或open函数中把该流与一个特定的磁盘文件关联起来。在各种情况下,描述文件的参量是相同的。
当你打开一个与输出流关联.的文件时,通常指定一个open_mode标志,如下表所示。可以用按位OR(|)运算符组合这些标志,它们作为枚举器定义在ios类中。
表  输出文件流文件打开模式
标  志 功         能
ios::app 打开一个输出文件用于在文件尾添加数据
ios::ate 打开一个现存文件(用于输入或输出)并查找到结尾
ios::in 打开一个输入文件对于一个ofstream文件,使用ios::in作为一个openmode可避免删除一个现存文件中现有的内容 ios::out    打开二个文件,用于输出。对于所有ofstream对象,此模式是隐含指定的 ios::nocreate    如果一个文件存在则打开它,否则该操作失败 i。
s::noreplace 如果一个文件不存在则作为新文件打开它,如果文件已存在,则该操作失败
ios::trunc 打开一个文件,如果它已经存在则删除其中原有的内容如果指定了ios::out,但没有指定iOs::ate、iOs::app和ios::in,则隐含为此模式
ios::binary 以二进制模式打开一个文件(缺省是文本模式)
有三个公共输出流涉及模式选项:
•建立一个文件,如果该文件己存在,则删除旧的版本:
ostream ofile("FILENAME");//缺省模式是ios::out
ofstream ofile("FILENAME",ios::out);//与上一句等效
•添加记录到一个现存文件中,如果文件不存在便建立一个新文件:
ofstream ofile(“FiILENAME”,ios::app);
•使用同一个流先后打开不同的文件(在同一时刻只有一个是打开的):
ofstream ofile();
ofile.open("FTILE1",ios::in)    //打开文件FILEl
…//    向文件FILEl
输出 ofile.close();    //关闭FILEl
ofile.open("FILE2",ios::in);    //打开文件FILE2
…//    向文件FILE2输出
ofile.close();    //关闭FILE2
//当对象ofile离开它的作用域时便消亡
2.put函数  
put函数把一个字符写到输出流中,下面两个语句缺省是相同的,但第二个受该流的格式化参量的影响:
cout.put(‘A’);    //精确地输出一个字符
cout<<"A";    //输出一个字符,但此前设置的宽度和填充方式在此起作用
3.write函数
write函数把一个内存中的一块内容写到一个输出文件流中,长度参数指出写的字节数。下面的例子建立一个输出文件流并将Date结构的二进制值写入文件:
例   向文件输出
#i nclude<fstream.h>
struct Date    
{
    int mo,da,yr;
};    
void main()
{    
    Date dt={6,10,92};
    ofstream tfile("date.dat",ios::binary);
    tfile.write((char*)&dt,sizeof dt);
}
write函数当遇到空字符时并不停止,因此能够写入完整的类结构,该函数带两个参量,一个char指针(指向内存数据的起始地址)和一个所写的字节数。注意在该结构对象的地址之前需要char*做强制类型转换。
4.seekp和tellp函数    
一个输出文件流保存一个内部指针指出下一次写数据的位置。seekp成员函数设置这个指针,因此可以以随机方式向磁盘文件输出。tellp成员函数返回该文件位置指针值。
5.输出流的close函数  
close成员函数关闭与一个输出文件流关联的磁盘文件。文件使用完毕后必须将其关闭以完成所有磁盘输出。虽然ofstream析构函数(destructor)会自动完成关闭,但如果需要在同一流对象上打开另外的文件,就需要使用close函数。    
如果构造函数或open成员函数打开了该文件,输出流析构函数自动关闭一个流的文件。
6.错误处理函数
错误处理成员函数的作用是在写到一个流时进行错误处理。各函数及其功能如下表所示。    
错误处理成员函数及其功能
函  数 功能及返回值
bad 如果出现一个不可恢复的错误,则返回一个非0值
fail 如果出现一个不可恢复的错误或一个预期的条件,例如一个转换错误或文件未找到,用返回一个非0值。在用零参量调用clear之后可能经常恢复处理
good 如果没有错误条件(不可恢复的或其他)和没有设置文件结尾标志,则返回一个非0值
eof 遇到文件结尾条件,则返回一个非0值
clear 设置内部错误状态,如果用缺省参量调用,则清除所有错误位
rdstate 返回当前错误状态
                          
! 运算符经过了重载,它与fail函数执行相同的功能,因此表达式if(! cout)等价于 if (cout.fail())。
void*()运算符也是经过重载的,与!运算符相反,因此表达式if(cout)等价于if(! cout.fail())。
void*()运算符不等价于good,因为它不检测文件结尾。
(四)二进制输出文件
最初设计流的目的是用于文本,因此缺省的输出模式是文本方式。在以文本模式输出时,若遇到换行符(十进制10),便自动被扩充为回车换行符(十进制13)。这种自动扩充有时可能出问题,请看下列程序:
#i nclude<fstream.h>
int iarray[2]={99,10};
void main()
{
    ofstream os("test.dat");
    os.write((char  *)iarray,sizeof(iarray));
}  
  
当执行程序,向文件中输出时,10会被自动转换成13,然而这里的转换显然不是我们需要的。要想解决这一问题,就要采用二进制模式输出。使用二进制模式输出时,其中所写的字符是不转换的。使用二进制模式输出到文件有下列几种方法,
(1)以通常方式构造一个流,然后使用setmode成员函数,在文件打开后改变模式,例如:
    ofstream ofs("test.dat");
    ofs.setmode(filebuf::binary);
ofs.write((char*)iarray,4);    //向二进制文件中写入4字节数据
(2)使用ofstream构造函数中的模式参量指定二进制输出模式,例如:
#i nclude<fstream.h>
#i nclude<fcntl.h>
#i nclude<io.h>
int iarray[2]={99,10};
void main()
{
ofstream ofs("test.dat",ios::binary);
ofs.write((char*)iarray,4);    //向二进制文件中写入4字节数据
}
(3)使用二进制操作符代替setmode成员函数:
ofs<<binary;
若使用text操作符便把流切换到文本转换模式。
(4)使用open函数带一个二进制模式标志打开文件,例如:
filedesc fd=open("test.dat",OBINARY|OCREAT|OWRONLY);
ofstream ofs(fd);
ofs.write((char*)iarray,4);    //向二进制文件中写入4字节数据

二.输入流成员函数

输人流成员函数用于从磁盘文件中输入,这些成员函数包括:
    •open函数    
    •get函数    
    •getline函数
    •read函数    
    •seekg和tellg函数
    •close函数    
1.输入流的open函数
如果要使用一个输入文件流(ifstream),必须在构造函数中或者使用open函数把该流与一个特定磁盘文件关联起来。无论哪种方式,参量是相同的。
当打开与一个输入流关联的文件时,通常要指定一个模式标志。模式标志如下表所示,该标志可以用按位OR(|)运算符进行组合。
表  输入文件流文件打开模式
ios::in    打开文件用于输入(缺省)
ios::nocreate   如果文件不存在,该函数失败
ios::binary 以二进制模式(缺省模式是文本模式)打开文件
注意:如果需要测试文件是否存在,必须在打开文件时指定ios::nocreate模式,然后使用fail成员函数确定:
    istream ifile("FILENAME",ios::nocreate);
    if (ifile.fail())
    //The file does not exist...
2.get函数    
非格式化get函数的功能与提取运算符(>>)很相像,主要的不同点是get函数在读人数据时包括空白字符,而提取运算符在缺省情况下拒绝接受空白字符。
例  get函数应用举例
#i nclude<iostream.h>
void main()    
{
    char ch;
    while((ch=cin.get())!=EOF)
  cout.put(ch);
}
运行时如果输入:
abc  xyz  123
则输出:
abc  xyz  123
3.getline函数
getline成员函数的功能是允许从输人流中读取多个字符,并且允许指定输入终止字符(缺省值是换行字符),在读取完成后,从读取的内容中删除该终止字符。
例   为输入流指定一个终止字符
本程序连续读人一串字符,直到遇到字符‘t’时停止,字符个数最多不超过99个。
  #i nclude<iostream.h>
void main()
{    
    char line[100];
    cout<<"Type a 1ine terminated by "t""<<endl;
    cin.getline(1ine,100,"t");
    cout<<line;
}
4.read函数
read成员函数从一个文件读字节到一个指定的存储器区域,由长度参数确定要读的字节数。如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时读结束。
例   从一个payroll文件读一个二进制记录到一个结构中
    #i nclude<io.h>
void main()    
{
    struct
    {
  double salary;
  char name[23];
}employee;
ifstream is("payroll",ios::binary|ios::nocreate);
    if (is)
    {
    is.read((char*)&employee,sizeof(employee));
    cout<<employee.name<<" "<<employee.salary<<endl;
    }
    else
    {
    cout<<"ERROR:Cannot openfile"payroll"."<<endl;
    }    
}    
这里假设数据记录是通过指定的结构严格格式化的,并且设有终止的回车或换行字符。
5.seekg和tellg函数    
在输入文件流中,保留着一个指向文件中下一个将读数据的位置的内部指针,可以用 seekg函数来设置这个指针。    
    例   用seekg函数设置位置指针
  #i nclude<fstream.h>
void main()
{    
char ch;
ifstream tfile("payroll",ios::binary | ios::nocreate);
if(tfile)    
{
  tfile.seekg(8);    
  while(tfile.good())    
  {
   //遇到文件结束或读取操作失败时结束读操作
   tfile.get(ch);
   if (!ch)break;    //如果没有读到则退出循环
   cout<<ch;
  }
    }
    else
    {
  cout<<"ERROR;Cannot open file "payroll"."<<endl;
}    
}
  
使用seekg可以实现面向记录的数据管理系统,用固定长度的记录尺寸乘以记录号便得到相对于文件末尾的字节位置,然后使用get读这个记录。
tellg成员函数返回当前文件读指针的位置,这个值是streampos类型,该typedef结构定义在iostream.h中。
例   读一个文件并显示出其中空格的位置
#i nclude<fstream.h>
void main()
{    
    char ch;
    ifstream tfile("payroll",ios::binary | ios::nocreate);
    if (tfile)    
    {    
  while(tfile.good())    
  {
   streampos here=tfile.tellg();
   tfile.get(ch);
   if(ch==" ")
    cout<<"\nPosition"<<here<<"is a space";
  }
    }    
    else
    {    
   cout<<"ERROR:Cannot open file "payroll"."<<endl;
    }
}    
6.输入流的close函数
close成员函数关闭与一个输入文件流关联的磁盘文件。
虽然ifstream类的析构函数可以自动关闭文件,但是如果需要使用同一流对象打开另一文件,则首先要用close函数关闭当前文件。
四、输入/输出流
一个iostream对象可以是数据的源或目的。两个重要的I/O流类都是从iostream派生的,它们是fstream和strstream。这些类继承了前面描述的stream和ostream类的功能。
fstream类支持磁盘文件的输入和输出。如果你需要在同一个程序中从一个特定磁盘文件读和写到该磁盘文件,可以构造一个fstream对象。一个istream对象是有两个逻辑子流的单个流,两个子流一个用于输入,另一个用于输出。详细说明请读者参考联机帮助或运行库参考手册

posted on 2011-01-15 14:45  李sir  阅读(3931)  评论(0编辑  收藏  举报