【C++】ファイルの内容を全て一度に読み込む方法 (istreambuf_iterator)

目次

はじめに

C++でファイルの内容を全て vectorstring に読み込みたい場合、while ループで1文字または1行ずつ読み込んでいくのが基本的な方法です。しかし、この方法はコードが冗長になりがちです。

よりモダンで簡潔なアプローチが、std::istreambuf_iterator を使う方法です。これは、入力ストリーム(ファイルなど)のバッファを直接読み取る特殊なイテレータです。コンテナの範囲コンストラクタと組み合わせることで、ファイルの内容全体を、たった一行でコンテナに流し込むことができます。


ファイル全体を一度に読み込むサンプルコード

このコードは、まずテスト用のファイル data.bin を作成し、その後 std::ifstreamstd::istreambuf_iterator を使って、そのファイルの内容を vector<char> に一括で読み込みます。

完成コード

#include <iostream>
#include <fstream>   // ifstream, ofstream
#include <vector>
#include <iterator>  // istreambuf_iterator
#include <string>

using namespace std;

int main() {
    const string filename = "data.bin";
    
    // 1. テスト用のファイルを作成
    ofstream ofs(filename, ios_base::binary);
    ofs << "Hello, C++!";
    ofs.close();
    
    // 2. ファイルをバイナリモードで開く
    ifstream ifs(filename, ios_base::binary);
    
    // ファイルが開けなかった場合のエラーチェック
    if (!ifs) {
        cerr << "ファイルを開けません: " << filename << endl;
        return 1;
    }

    // 3. istreambuf_iteratorを使って、ファイル全体をvectorに一括で読み込む
    vector<char> file_contents(
        (istreambuf_iterator<char>(ifs)), // 開始イテレータ
        (istreambuf_iterator<char>())    // デフォルトコンストラクタで終了イテレータ
    );

    // 4. 読み込んだ内容を確認
    cout << "ファイルから読み込んだ内容 (" << file_contents.size() << "バイト):" << endl;
    for (char c : file_contents) {
        cout << c;
    }
    cout << endl;

    return 0;
}

コードの解説

vector<char> file_contents( (istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()) );

これが、ファイル全体を読み込む核心部分であり、「イテレータペアコンストラクタ」と呼ばれる vector のコンストラクタを利用しています。

  • vector<char> file_contents(...): vector のコンストラクタは、開始イテレータと終了イテレータを引数として受け取り、その範囲の要素で vector を初期化できます。
  • istreambuf_iterator<char>(ifs): これが開始イテレータです。ifstreamオブジェクト ifs を引数としてコンストラクタを呼び出すと、そのファイルの先頭を指す istreambuf_iterator が生成されます。
  • istreambuf_iterator<char>(): こちらが終了イテレータです。istreambuf_iterator は、引数なしのデフォルトコンストラクタで生成すると、ストリームの終端を表す特別なイテレータになります。

vector のコンストラクタは、開始イテレータから始まり、終了イテレータに到達するまで、ストリームから文字を一つずつ読み込んで vector に追加していきます。istreambuf_iterator はバッファを直接読むため、非常に高速に動作します。


まとめ

今回は、C++の std::istreambuf_iterator を使って、ファイルの内容をコンテナに一括で、かつ効率的に読み込む方法を解説しました。

  • std::istreambuf_iterator は、入力ストリームのバッファを直接読む高速なイテレータ。
  • vector などの範囲コンストラクタと組み合わせることで、ファイル全体を一行で読み込める。
    • コンテナ変数( (istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()) )

このイディオム(定石)は、バイナリファイルやテキストファイルをまとめてメモリに読み込んでから処理したい場合に、非常に強力で簡潔な方法です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次