C++ でファイルを文字列に読み込む

胡金庫 2023年10月12日
  1. C++ でファイルを文字列に読み込むには istreambuf_iterator を使用する
  2. C++ でファイルを文字列に変換して読み込むには rdbuf を使用する
  3. ファイルを文字列に読み込むには fread を使用する
  4. ファイルを文字列に読み込むには read を用いる
C++ でファイルを文字列に読み込む

この記事では、C++ でファイルの内容を std::string に読み込むいくつかの方法を説明します。

C++ でファイルを文字列に読み込むには istreambuf_iterator を使用する

istreambuf_iteratorstd::basic_streambuf オブジェクトから連続した文字を読み込む入力イテレータです。したがって、istreambuf_iteratorifstream のストリームと一緒に利用して、ファイルの全内容を std::string に読み込むことができます。

まず、与えられたファイルのパスを ifstream オブジェクトとして開きます。次に istreambuf_iterator<char>(input_file)string のコンストラクタに渡して、必要なオブジェクトを取得します。ここでは、関数から返すために string のコンストラクタ文を直接渡していることに注意してください。プログラムの出力は、変数 filename で指定されたファイルの内容でなければならません。

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

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

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 <fstream>
#include <iostream>
#include <sstream>

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

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 は 4つの引数を取ります。

  1. 読み込んだデータが格納されているバッファへのポインタ。
  2. データ項目のサイズ。
  3. データ項目の数
  4. 読み込むファイルポインタ。

ファイル全体を読み込むので、ファイルサイズを取得する必要があり、stat Unix システムコールで実装します。ファイルサイズを取得したら、その値をデータ要素のサイズとして fread 関数に渡し、データ項目の数として 1 を指定します。

開いたファイルは、ファイルポインタの唯一の引数を取る fclose 関数呼び出しで閉じる必要があることに注意してください。

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

#include <iostream>

using std::cerr;
using std::cout;
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 関数の他の 2つの引数は、データが格納されるバッファへのポインタと読み込みに必要なバイト数であり、後者は fstat 関数呼び出しで取得されています。読み込んだファイルの内容を格納するバッファとして string.data を用いていることに注意してほしい。

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

#include <iostream>

using std::cerr;
using std::cout;
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);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C++ File