はじめに
C++のファイルストリーム (fstream
) や文字列ストリーム (stringstream
) を扱う際、通常は先頭から末尾へ順番に読み書きを行いますが、時には「特定のバイト位置まで一気に移動したい」「一度読んだ場所まで戻って、もう一度読み直したい」というように、読み書きする位置を自由に制御したい場合があります。
このファイルポインタ(ストリーム内の現在位置)の操作は、以下の4つのメンバ関数で行います。
- 入力ストリーム (
istream
):tellg()
: 現在の読み取り位置 (get position) を取得する。seekg()
: 読み取り位置 (seek get) を移動する。
- 出力ストリーム (
ostream
):tellp()
: 現在の書き込み位置 (put position) を取得する。seekp()
: 書き込み位置 (seek put) を移動する。
この記事では、これらの関数を使って、ストリーム内の任意の位置にアクセスする方法を解説します。
1. 入力ストリームの位置を操作する (tellg
, seekg
)
このコードは、文字列ストリームから最初の単語を読み取った後、tellg
でその位置を記録し、次の単語を読み飛ばした後、seekg
で記録した位置に戻って、2番目の単語を読み直します。
サンプルコード
#include <iostream>
#include <sstream> // istringstream
#include <string>
using namespace std;
int main() {
istringstream iss("One Two Three");
string word1, word2, word3;
// 最初の単語 "One" を読み込む
iss >> word1;
// 1. tellg()で現在の読み取り位置を取得
streampos read_position = iss.tellg();
cout << "「One」を読んだ後の位置: " << read_position << endl;
// 2番目の単語 "Two" を読み飛ばす
iss >> word2;
// 2. seekg()で、記録した位置に戻る
iss.seekg(read_position);
// 3. 再び読み込むと、2番目の単語 "Two" が読み取れる
iss >> word3;
cout << "読み直した単語: " << word3 << endl;
return 0;
}
2. 出力ストリームの位置を操作する (tellp
, seekp
)
このコードは、文字列ストリームに文字列を書き込んだ後、seekp
を使って先頭に戻り、内容の一部を上書きします。
サンプルコード
#include <iostream>
#include <sstream> // ostringstream
#include <string>
using namespace std;
int main() {
ostringstream oss;
oss << "Hello, world!";
cout << "書き込み前: " << oss.str() << endl;
// 1. seekp()で、書き込み位置を先頭から7バイト目に移動
oss.seekp(7);
// 2. その位置から "C++" を書き込む
oss << "C++";
cout << "書き込み後: " << oss.str() << endl;
return 0;
}
seek
関数の基準位置
seekg
と seekp
は、移動の基準となる位置を指定できます。 stream.seekg(オフセット, 基準位置);
ios_base::beg
: ストリームの先頭(begin)を基準とする。(デフォルト)ios_base::cur
: 現在位置(current)を基準とする。ios_base::end
: ストリームの末尾(end)を基準とする。
例: ifs.seekg(-10, ios_base::end);
// 末尾から10バイト前に移動
まとめ
今回は、C++のストリームにおける読み書き位置の制御方法を解説しました。
操作 | 入力 (get) | 出力 (put) |
位置の取得 | tellg() | tellp() |
位置の移動 | seekg() | seekp() |
Google スプレッドシートにエクスポート
これらの関数は、バイナリファイルを直接操作して特定のデータ構造を読み書きしたり、既存のファイルの一部を上書き修正したりといった、高度なファイル操作を行う上で不可欠なツールです。