C++文件输入输出流(无师自通)

输入流是可以读取数据的序列;输出流是可以写入数据的序列;而输入输出流是允许读取和写入的一系列数据。键盘是输入流的标准示例,显示器屏幕是输出流的标准示例。

C++ 提供了用于处理流的各种类。这些类包括:
  • 执行标准输入和输出的 istream 和 ostream;
  • 用于文件输入输出的 ifstream、ofstream 和 fstream;
  • 用于读写字符串的 istringstream 和 ostringstream。

要从键盘上读取输入,可以使用 cin,它是 istream 类的预定义对象;要写入屏幕,可以使用 cout,它是 ostream 类的预定义对象。本节将讨论 fstream 类,它允许一个文件同时用于输入和输出。

ifstream、ofstream 和 fstream 类非常相似。它们 3 个都有一个默认的构造函数,允许创建类的实例:

ifstream();
ofstream();

此外,它们每一个都有初始化构造函数,可以釆用两个形参:要打开的文件名和打开模式。文件名通过 C 字符串给定。打开模式则是一项决定如何使用文件的设置。

初始化构造函数具有以下原型:

ifstream(const char* filename, ios::openmode mode = ios::in)
ofstream(const char* filename, ios::openmode mode = ios::out)
ffstream(const char* filename, ios::openmode mode = ios::in | ios::out)

从 C++ 11 开始,可以对文件名使用 string 对象:

ifstream(const strings filename, ios::openmode mode = ios::in)
ofstream(const strings filename, ios::openmode mode = ios::out)
ffstream(const strings filename, ios::openmode mode = ios::in | ios::out)

打开模式形参是可选项。在未指定时,打开模式默认为初始化构造函数中显示的值。

所有这 3 个文件流类都有可以打开文件的成员函数,它们的形参与初始化构造函数中的形参类似。例如,fstream 的 open 函数具有以下原型:

void open (const char* filename, ios::openmode mode = ios::in | ios::out)
void open(const strings filename, ios::openmode mode = ios::in | ios::out)

这 3 个类也都有一个 close 成员函数,用于在程序使用完文件时断开连接:

void close ();

打开的文件使用操作系统中的资源,所以一旦使用完,关闭文件就非常重要。另外,程序写入文件流对象的数据通常会在操作系统中缓冲,而不会立即写入磁盘。关闭文件时,操作系统将这些数据写入磁盘,这个过程称为冲刷缓冲区。关闭文件将确保缓冲数据不会在电源故障或其他导致程序异常终止的情况下丢失。

fstream 类本身结合了 ifstream 和 ofstream 的功能,因此 fstream 拥有这两个类的所有成员函数和运算符。尤其是,可以使用提取运算符 >> 和插入运算符 << 在 fstream 对象上读写数据。

在默认情况下,ifstream 对象打开文件进行输入,ofstream 对象打开文件进行输出,而 fstream 对象则可以打开文件进行输入和输出。下面的程序给出了一个简单的例子,它使用 fstream 对象来打开一个文件进行读写:
//This program demonstrates reading and writing
//a file through an fstream object
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
    fstream inOutFile;
    string word; // Used to read a word from the file
    // Open the file
    inOutFile.open ("inout.txt");
    if (!inOutFile)
    {
        cout << "The file was not found." << endl;
        return 1;
    }
    // Read and print every word already in the file
    while (inOutFile >> word)
    {
        cout << word << endl;
    }
    // Clear end of file flag to allow additional file operations
    inOutFile.clear ();
    // Write a word to the file and close the file
    inOutFile << "Hello" << endl;
    inOutFile.close ();
    return 0;
}
程序输出结果:

Hello
Hello
Hello

程序中,只有当提取运算符到达文件末尾,无法读取到下一个单词时,第 20〜23 行的循环才会终止。每当出现输入或输出操作失败时,文件流对象会设置许多错误标志。一旦设置了错误标志,流将不允许对其执行进一步的操作,直到错误标志被清除。第 25 行调用 clear 函数将清除这些标记,从而允许第 27 行和第 28 行中的语句成功执行。