C++ でファイルを文字列に読み込む
- 
          
            C++ でファイルを文字列に読み込むには istreambuf_iteratorを使用する
- 
          
            C++ でファイルを文字列に変換して読み込むには rdbufを使用する
- 
          
            ファイルを文字列に読み込むには freadを使用する
- 
          
            ファイルを文字列に読み込むには readを用いる
 
この記事では、C++ でファイルの内容を std::string に読み込むいくつかの方法を説明します。
C++ でファイルを文字列に読み込むには istreambuf_iterator を使用する
    
istreambuf_iterator は std::basic_streambuf オブジェクトから連続した文字を読み込む入力イテレータです。したがって、istreambuf_iterator を ifstream のストリームと一緒に利用して、ファイルの全内容を 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つの引数を取ります。
- 読み込んだデータが格納されているバッファへのポインタ。
- データ項目のサイズ。
- データ項目の数
- 読み込むファイルポインタ。
ファイル全体を読み込むので、ファイルサイズを取得する必要があり、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);
}
