C++檔案輸入輸出流(無師自通)

2020-07-16 10:04:42
輸入流是可以讀取資料的序列;輸出流是可以寫入資料的序列;而輸入輸出流是允許讀取和寫入的一系列資料。鍵盤是輸入流的標準範例,顯示器螢幕是輸出流的標準範例。

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 行中的語句成功執行。