在 C++ 中將檔案讀入到字串

Jinku Hu 2023年1月30日 2020年12月31日
  1. 使用 istreambuf_iterator 在 C++ 中將檔案讀入到字串
  2. 在 C++ 中使用 rdbuf 將檔案讀入字串
  3. 使用 fread 將檔案讀入字串
  4. 使用 read 將檔案讀成字串
在 C++ 中將檔案讀入到字串

本文將講解幾種在 C++ 中把檔案內容讀取到 std::string 的方法。

使用 istreambuf_iterator 在 C++ 中將檔案讀入到字串

istreambuf_iterator 是一個輸入迭代器,從 std::basic_streambuf 物件中讀取連續的字元。因此,我們可以利用 istreambuf_iteratorifstream 流一起使用,並將檔案的全部內容讀取到 std::string 中。

首先,我們開啟一個給定的檔案路徑作為 ifstream 物件。然後,我們可以將 istreambuf_iterator<char>(input_file) 傳遞給 string 建構函式,並在第一時間得到我們需要的物件。注意,我們是直接傳遞 string 建構函式語句,從函式中返回。程式的輸出應該是由 filename 變數指定的檔案內容。

#include <iostream>
#include <fstream>
#include <sstream>

using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;

string readFileIntoString(const string& path) {
    ifstream input_file(path);
    if (!input_file.is_open()) {
        cerr << "Could not open the file - '"
             << path << "'" << endl;
        exit(EXIT_FAILURE);
    }
    return string((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>());
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}

在 C++ 中使用 rdbuf 將檔案讀入字串

rdbuf 函式是一個內建的方法,用來返回檔案的流緩衝區的指標,這對於使用 << 運算子將檔案的全部內容插入到需要的物件中是很有用的。

在下面的例子中,我們構造了一個 ostringstream 物件,在這個物件中插入 rdbuf 函式的返回值。函式本身返回的是 string 物件,所以使用 str 方法來獲取最終的返回值。

#include <iostream>
#include <fstream>
#include <sstream>

using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;

string readFileIntoString2(const string& path) {
    auto ss = ostringstream{};
    ifstream input_file(path);
    if (!input_file.is_open()) {
        cerr << "Could not open the file - '"
             << path << "'" << endl;
        exit(EXIT_FAILURE);
    }
    ss << input_file.rdbuf();
    return ss.str();
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString2(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}

使用 fread 將檔案讀入字串

另一種讀取檔案的方法是 C 標準庫函式 fread。這種方法需要相對較舊的函式,在現代 C++ 程式碼庫中並不常見,但與以前的方法相比,它在速度方面有優勢。

fread 需要四個引數。

  1. 一個指向儲存讀取資料的緩衝區的指標。
  2. 資料項的大小。
  3. 資料項的數量。
  4. 讀取的檔案指標。

由於我們要讀的是整個檔案,所以需要檢索檔案大小,並通過 Unix 系統呼叫 stat 實現。檢索到檔案大小後,我們將其值作為資料元素的大小傳遞給 fread 函式,並將資料項的數目指定為 1

需要注意的是,開啟的檔案需要用 fclose 函式呼叫來關閉,它的唯一引數是檔案指標。

#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

using std::cout; using std::cerr;
using std::endl; using std::string;

string readFileIntoString3(const string& path) {
    struct stat sb{};
    string res;

    FILE* input_file = fopen(path.c_str(), "r");
    if (input_file == nullptr) {
        perror("fopen");
    }

    stat(path.c_str(), &sb);
    res.resize(sb.st_size);
    fread(const_cast<char*>(res.data()), sb.st_size, 1, input_file);
    fclose(input_file);

    return res;
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString3(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}

使用 read 將檔案讀成字串

read 方法是符合 POSIX 標準的函式呼叫,在各種作業系統上都可以使用,如果程式設計師懂得有效地運用它,那麼它可以成為最靈活的一種方法。fread 本身會在下面呼叫 read,但這並不能保證在所有情況下都有更快的操作,因為多種因素對這種系統呼叫的有效使用起著影響。

fread 的主要區別在於,read 需要一個檔案描述符引數來指向從哪裡讀取資料的檔案。檔案描述符是與程式在執行過程中可能具有的開啟的檔案流相關聯的特殊整數。它可以使用 open 函式呼叫獲得,並以 int 型別儲存。read 函式的另外兩個引數是指向將儲存資料的緩衝區的指標和需要讀取的位元組數,後者用 fstat 函式呼叫檢索。注意,我們使用 string.data 作為緩衝區來儲存讀取的檔案內容。

#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

using std::cout; using std::cerr;
using std::endl; using std::string;

string readFileIntoString4(const string& path) {
    struct stat sb{};
    string res;

    int fd = open(path.c_str(), O_RDONLY);
    if (fd < 0) {
        perror("open\n");
    }

    fstat(fd, &sb);
    res.resize(sb.st_size);
    read(fd, (char*)(res.data()), sb.st_size);
    close(fd);

    return res;
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString4(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相關文章 - C++ File