## 14.2 明示的な同期

ストリームバッファの関数 `pubsync()` を使用して、ストリームのバッファを出力ファイルに強制的に移動したり、入力ファイルの内容を強制的にバッファに移動することができます。 一般に、`pubsync()` はストリーム層の関数で間接的に呼び出します。入力ストリームと出力ストリームには異なるメンバー関数があり、暗黙的に `pubsync()` を呼び出します。

### 14.2.1 出力ストリーム

出力ストリームには `flush()` 関数があり、バッファの内容をファイルに書き込みます。エラーが発生すると、`badbit` が設定されるか、例外マスクの内容によっては、例外が送出されます。

>     ofstream ofstr("/tmp/fil");
>     ofstr << "Hello ";                                            //1
>     ofstr << "World!\n";
>     ofstr.flush();                                                //2

//1 | この挿入後にファイル `/tmp/fil` から何かを抽出しようとしても、おそらくエラーになります。文字列 `"Hello "` はバッファにあり、外部ファイルにはまだ書き込まれていないためです。
//2 | しかし、`flush()` に対する呼び出し後、ファイル `/tmp/fil` には "`Hello World!\n"` が転送されています (また、`ostr.flush()` に対する呼び出しは、`ostr << flush;` のように `flush` マニピュレータによって置換することができます)。

ここで、フラッシュには時間がかかることに注意してください。関数 `flush()` では、バッファの内容をファイルに書き込むと共に、現在のファイル位置を維持するために、バッファに新たな抽出を行います。パフォーマンスの面からは、行末文字の装入時に `endl` マニピュレータで `flush()` を呼び出すときのような不用意なフラッシュは避けるべきです (7.3.2 節 を参照)。

### 14.2.2 入力ストリーム

入力ストリームには `sync()` 関数があり、ストリームで現在のファイル位置から外部デバイスを強制的にアクセスし、バッファにデータを抽出します。22次の例は、この原理を理論的に説明したものです。実際には、2 つのストリームは異なる 2 つのプロセスに所属し、共有ファイルでデータのやりとりを行います。

>     ofstream ofstr("/tmp/fil");
>     ifstream ifstr("/tmp/fil");
>     string s;

>     ofstr << "Hello "
>     ofstream::pos_type p = ofstr.tellp();
>     ofstr << "World!\n" << flush;
>     ifstr >> s;                                                   //1

>     ofstr.seekp(p);
>     ofstr << "Peter!" << flush;                                   //2
>     ifstr >> s;                                                   //3

>     ofstr << " Happy Birthday!\n" << flush;                       //4
>     ifstr >> s;                                                   //5

>     ifstr.sync();                                                 //6
>     ifstr >> s;

//1 | ここで、入力ストリームは共有ファイルから最初の文字列を抽出します。入力ストリームは、バッファにデータを抽出します。内部バッファが一杯になるまで、外部ファイルから文字を抽出します。そのため、ファイルから抽出する文字数は実装によって異なり、内部ストリームバッファのサイズで決まります。
//2 | ファイルの内容が、部分的に出力ストリームによって上書きされます。 これで、ファイルの内容と入力ストリームのバッファの内容が一致しなくなります。ファイルの内容は `"Hello Peter!"` ですが、入力ストリームのバッファの内容は、依然として `"Hello World!"` です。
//3 | この抽出では、現在のファイルの内容である `"Peter!"` を抽出する代わりに、バッファから文字列 `"World!"` が抽出されます。
//4 | 外部ファイルには、さらに文字が追加されます。ファイルの内容は、この時点で `"Hello Peter! Happy Birthday!``"``` となっていますが、入力ストリームのバッファの内容は変更されていません。
//5 | この抽出では何も生成されません。この簡単な例ではファイルが小さいため、入力ストリームでは、ファイルの内容がすべてバッファに抽出されます。その後の抽出で、入力ストリームによってバッファの最後まで抽出され、これでファイルも最後であるとみなされます。この抽出で `eofbit` が設定され、何も抽出されません。再び外部ファイルを抽出する理由がなくなりました。
//6 | `sync()` に対する呼び出しでは、最終的に入力ストリームによって、外部デバイスのデータが現在のファイル位置からバッファに抽出されます。同期後、入力ストリームのバッファ の内容は、`"Happy Birthday!\n"` になります。次の抽出では、`"Happy"` が生成されます。 以上の例では、`sync()` を実装定義としているため、`istr.seekg(ios_base::cur);` とすることで、入力ストリームを現在の位置に変更することもできます。

> 注: 1 つのファイルを共有する複数のストリームを同期する場合は、出力演算の後と入力演算の前の間に `sync()` 関数を呼び出すと有用です。

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。

OEM リリース, 1998 年 6 月