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);
}