C++文件讀寫

本文主要用於探討使用C++來進行文件讀寫操作。

在C++中,所有的輸入輸出操作大部分都繼承自 ios_base 基類,詳細的繼承體系如下圖所示

fstream的使用

在fstream類中,成員函數open()實現打開文件的操作,從而將數據流和文件進行關聯,通過ofstream,ifstream,fstream對象進行對文件的讀寫操作,同時在打開文件時,可以指定打開的模式,如讀、寫或者讀寫,可選模式如下

mode detail
ios::in 為輸入(讀)而打開文件
ios::out 為輸出(寫)而打開文件
ios::ate 初始位置:文件尾
ios::app 所有輸出附加在文件末尾
ios::trunc 如果文件已存在則先刪除該文件
ios::binary 二進位方式

open的定義方式

void open(const wchar_t *_Filename, 
    ios_base::openmode mode= ios_base::in | ios_base::out;

void open(const wchar_t *_Filename, 
    ios_base::openmode mode= ios_base::in | ios_base::out, 
    int prot = ios_base::_Openprot);

其中,filename表示操作文件名,mode表示打開文件的方式,prot表示打開文件的屬性。在打開文件時,在stream類的構造函數中調用open()函數都有自己默認的操作方式

ofstream out("...", ios::out);  
ifstream in("...", ios::in);  
fstream foi("...", ios::in|ios::out); 

使用write()read()函數進行文件讀寫

int main(){
    string file_path = "test.txt";
    char info[] = "hello fan";
    char buffer[256];
    ofstream out(file_path, ios::binary);
    if(out.is_open()){
        out.write(info, sizeof(info));
        out.close();
    }
    ifstream in(file_path, ios::binary);
    if(in.is_open()){
        while(!in.eof()){
            in.read(buffer, 100);
            cout << buffer << endl;
        }
        in.close();
    }

    return 0;
}
// out
/*
hello fan
*/

ofstream重載了 <<操作符可用來向文件輸出數據,ifstream重載了>>操作符,可用來讀入數據。

#include <iostream>
#include<fstream>
#include<string>

using namespace std;

int main(){
    string file_path = "test.txt";
    char buffer[256];
    ofstream out(file_path);
    if(out.is_open()){
        out << "hello ";
        out << "fan";
        out.close();
    }
    ifstream in(file_path);
    if(in.is_open()){
        while(!in.eof()){
            in.getline(buffer, 100);
            cout << buffer << endl;
        }

    }
    return 0;
}
// hello fan

在上述程式碼中,使用is_open()函數,用來判斷文件是否正常打開,eof()函數用來判斷是否讀到文件末尾。

除了這些以外,還有一些驗證流的狀態的成員函數(所有都返回bool型返回值):

  • bad()
    如果在讀寫過程中出錯,返回 true 。例如:當我們要對一個不是打開為寫狀態的文件進行寫入時,或者我們要寫入的設備沒有剩餘空間的時候。

  • fail()
    除了與bad() 同樣的情況下會返回 true 以外,加上格式錯誤時也返回true ,例如當想要讀入一個整數,而獲得了一個字母的時候。

  • good()
    這是最通用的:如果調用以上任何一個函數返回true 的話,此函數返回 false 。

為了能夠更為方便地對文件進行操作,還需要能夠判斷我們讀文件讀到了哪裡,使用函數tellg/tellp 用於提取當前文件指針的位置,使用函數 seekg/seekp 來將文件指針移到某處

  • tellg() 和 tellp()
    這兩個成員函數不用傳入參數,返回pos_type 類型的值(根據ANSI-C++ 標準) ,就是一個整數,代表當前get 流指針的位置 (用tellg) 或 put 流指針的位置(用tellp).

  • seekg() 和seekp()
    這對函數分別用來改變流指針get 和put的位置。兩個函數都被重載為兩種不同的原型:

seekg ( pos_type position ); 
seekp ( pos_type position );

使用這個原型,流指針被改變為指向從文件開始計算的一個絕對位置。要求傳入的參數類型與函數 tellg 和tellp 的返回值類型相同。

seekg ( off_type offset, seekdir direction ); 
seekp ( off_type offset, seekdir direction );

使用這個原型可以指定由參數direction決定的一個具體的指針開始計算的一個位移(offset)。它可以是:

type detail
ios::beg 從流開始位置計算的位移
ios::cur 從流指針當前位置開始計算的位移
ios::end 從流末尾處開始計算的位移

示例

int main(){
    string file_path = "test.txt";
    char buffer[256];
    ifstream in(file_path);
    if(in.is_open()){
        auto site = in.tellg();
        in.seekg(site+6, ios::cur);
        while(!in.eof()){
            in.getline(buffer, 100);
            cout << buffer << endl;
        }

    }
    return 0;
}

上述文件中數據為 “hello fan”,輸出為 “fan”,因為開始時,文件指針指向文件開頭,使用tellg()函數獲取文件指針位置,然後使用seekg()函數將文件指針後移6個字元,因此讀取結果為 “fan”。

簡單文件讀寫示例

#include <iostream>
#include<fstream>
#include<string>

using namespace std;

int choose_mod(){
    int f = 0;
    cout << "----Easy file read and write----" << endl;
    cout << "Please choose write or read file" << endl;
    cout << "Enter 1, read file" << endl;
    cout << "Enter 2, write file" << endl;
    cout << "Enter 3, exit" << endl;
    cout << "--------------------------------" << endl;
    cin >> f;
    while(f != 1 && f != 2 && f != 3){
        cout << "Please choose 1 or 2 or 3" << endl;
        cin >> f;
    }

}

int main(){
    string file_name = "test.txt";
    int mod = choose_mod();
    char buffer[256];
    ifstream in;
    ofstream out;
    string tmp;

    while(mod != 3){
        if(mod == 1){
            in.open(file_name);
            if(in.is_open()){
                while(!in.eof()){
                    in.getline(buffer, 100);
                    cout << buffer << endl;
                }
                in.close();
            }
        }else{
            out.open(file_name, ios::app);
            if(out.is_open()){
                cout << "Please enter string, Enter quit end" << endl;
                tmp = "";
                while(true){
                    getline(cin, tmp);
                    if(tmp == "quit") break;
                    out << tmp << "\n";
                }
                out.close();
            }
        }
        mod = choose_mod();
    }
    cout << "Quit" << endl;

    return 0;
}

參考文獻

C++文件讀寫詳解
C++文件讀寫操作總結