8.2 文件输入输出

头文件fstream定义了三个类型来支持文件IO:ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据,以及fstream可以读写给定文件。这些类型提供的操作和cin和cout的操作一样。还可以用IO运算符(<<和>>)来读写文件,可以用getline从一个ifstream来读取数据。

一些fstream中特有的操作

------------------------------------------------- --
fstream fstrm; 创建一个未绑定的文件流。fstream 是头文件 fstream 定义的一个类型
fstream fstrm(s); 创建一个fstream,并打开名为s文件。s可以是string类型,或者是一个指向C风格字符串的指针。这些构造函数都是explicit的,默认的文件模式mode依赖于fstream类型
fstream fstrm(s,mode); 与前一个构造函数类似,但按指定mode打开文件
fstrm.open(s) 打开名为s文件,并将文件与fstrm绑定。s可以是string类型,或者是一个指向C风格字符串的指针。默认的文件模式mode依赖于fstream类型。返回void。
fstrm.close() 关闭与fstrm绑定的文件。返回void。
fstrm.is_open() 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭。

8.2.1 使用流对象

当想要读写一个文件时,可以定义一个文件流对象,并将对象与文件关联起来。每个文件流都定义了一个名为open的函数,它完成一些系统相关操作,来定位给定文件,并视情况打开为读或写的模式。

创建文件流对象时,我们可以提供文件名,如果提供了文件名,则open被自动调用。

ifstream in(ifile); //构造一个ifstream并打开文件
ofstream out; //输出文件流未关联到任何文件
  • 用fstream替代iostream&

在要求使用基类型对象的地方,可以用继承类型的对象来替代。如果有一个函数接受一个ostream&参数,在调用时,可以传递给它一个ofstream对象。

ifstream input(argv[1]); //打开销售记录文件
ofstream output(argv[2]); //打开输出文件
Sales_data total; //保存销售总额的变量
if (read(input, total)) 
{
  Sales_data trans; //保存下一条销售记录的变量
  while(read(input, trans))
  {
    if(total.isbn == trans.isbn())
      total.combine(trans);
    else
    {
      print(output, total)<<endl;
      total = trans ;
    }
  }
  print(output, total)<<endl;
}
else
  cerr << "No data ?" <<endl;

虽然read和print在定义时指定的形参分别是istream&和ostream&,但可以向它传递fstream对象。

  • 成员函数open和close 可以先定义空文件流对象,然后调用open将它与文件关联起来。
ifstream in(ifile); //构筑一个ifstream并打开给定文件
ofstream out; //输出流未与任何文件关联
out.open(ifile + ".copy"); //打开指定文件

如果调用open失败,failbit会被置位。应检测open是否成功。

if(out)

一旦一个文件流已经打开,它就保持与对应文件的关联。对一个已经打开的文件流调用open失败后,failbit被置位。随后试图使用文件流的操作都会失败。为了将文件流关联到另一个文件,必须首先关闭已经关联的文件。

in.close(); //关闭文件
in.open(ifile + "2"); //打开另一个文件

如果open成功,则open会使good()为true。

  • 自动构造和析构
for (auto p = argv +1; p != argv + argc; ++p)
{
  ifstream input(*p); //创建输出流并打开文件
  if(input)
  {
    process(input);
  }
  else
  {
    cerr << "couldn't open :" + string(*p);
  }
}

input是while的循环局部变量,它在每个步中都要创建销毁一次。当一个fstream离开它的作用域时,与之关联的文件会自动关闭(即close会被自动调用)。在下一步循环中,input会再次被创建。