Linux中國

如何用 C++ 讀寫文件

在 C++ 中,對文件的讀寫可以通過使用輸入輸出流與流運算符 >><< 來進行。當讀寫文件的時候,這些運算符被應用於代表硬碟驅動器上文件類的實例上。這種基於流的方法有個巨大的優勢:從 C++ 的角度,無論你要讀取或寫入的內容是文件、資料庫、控制台,亦或是你通過網路連接的另外一台電腦,這都無關緊要。因此,知道如何使用流運算符來寫入文件能夠被轉用到其他領域。

輸入輸出流類

C++ 標準庫提供了 ios_base 類。該類作為所有 I/O 流的基類,例如 basic_ofstreambasic_ifstream。本例將使用讀/寫字元的專用類型 ifstreamofstream

  • ofstream:輸出文件流,並且其能通過插入運算符 << 來實現。
  • ifstream:輸入文件流,並且其能通過提取運算符 >> 來實現。

該兩種類型都是在頭文件 <fstream> 中所定義。

ios_base 繼承的類在寫入時可被視為數據接收器,在從其讀取時可被視為數據源,與數據本身完全分離。這種面向對象的方法使 關注點分離 separation of concerns 依賴注入 dependency injection 等概念易於實現。

一個簡單的例子

本常式是非常簡單:實例化了一個 ofstream 來寫入,和實例化一個 ifstream 來讀取。

#include <iostream> // cout, cin, cerr etc...
#include <fstream> // ifstream, ofstream
#include <string>

int main()
{
    std::string sFilename = "MyFile.txt";    

    /******************************************
     *                                        *
     *                WRITING                 *
     *                                        *
     ******************************************/

    std::ofstream fileSink(sFilename); // Creates an output file stream

    if (!fileSink) {
        std::cerr << "Canot open " << sFilename << std::endl;
        exit(-1);
    }

    /* std::endl will automatically append the correct EOL */
    fileSink << "Hello Open Source World!" << std::endl;

    /******************************************
     *                                        *
     *                READING                 *
     *                                        *
     ******************************************/

    std::ifstream fileSource(sFilename); // Creates an input file stream

    if (!fileSource) {
        std::cerr << "Canot open " << sFilename << std::endl;
        exit(-1);
    }
    else {
        // Intermediate buffer
        std::string buffer;

        // By default, the >> operator reads word by workd (till whitespace)
        while (fileSource >> buffer)
        {
            std::cout << buffer << std::endl;
        }
    }

    exit(0);
}

該代碼可以在 GitHub 上查看。當你編譯並且執行它時,你應該能獲得以下輸出:

![Console screenshot](/data/attachment/album/202104/02/224559znrekkvosgldny2v.png "Console screenshot")

這是個簡化的、適合初學者的例子。如果你想去使用該代碼在你自己的應用中,請注意以下幾點:

  • 文件流在程序結束的時候自動關閉。如果你想繼續執行,那麼應該通過調用 close() 方法手動關閉。
  • 這些文件流類繼承自 basic_ios(在多個層次上),並且重載了 ! 運算符。這使你可以進行簡單的檢查是否可以訪問該流。在 cppreference.com 上,你可以找到該檢查何時會(或不會)成功的概述,並且可以進一步實現錯誤處理。
  • 默認情況下,ifstream 停在空白處並跳過它。要逐行讀取直到到達 EOF ,請使用 getline(...) 方法。
  • 為了讀寫二進位文件,請將 std::ios::binary 標誌傳遞給構造函數:這樣可以防止 EOL 字元附加到每一行。

從系統角度進行寫入

寫入文件時,數據將寫入系統的內存寫入緩衝區中。當系統收到系統調用 sync 時,此緩衝區的內容將被寫入硬碟。這也是你在不告知系統的情況下,不要卸下 U 盤的原因。通常,守護進程會定期調用 sync。為了安全起見,也可以手動調用 sync()

#include <unistd.h> // needs to be included

sync();

總結

在 C++ 中讀寫文件並不那麼複雜。更何況,如果你知道如何處理輸入輸出流,(原則上)那麼你也知道如何處理任何類型的輸入輸出設備。對於各種輸入輸出設備的庫能讓你更容易地使用流運算符。這就是為什麼知道輸入輸出流的流程會對你有所助益的原因。

via: https://opensource.com/article/21/3/ccc-input-output

作者:Stephan Avenwedde 選題:lujun9972 譯者:wyxplus 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國