はじめに
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 スプレッドシートにエクスポート
これらの関数は、バイナリファイルを直接操作して特定のデータ構造を読み書きしたり、既存のファイルの一部を上書き修正したりといった、高度なファイル操作を行う上で不可欠なツールです。
