VS 2008 Express では、ifstream シークビヨンドエンドは eof を返しませんか?
質問
VS 2005 には、次のようなコードがあります。
ifs.open("foo");
while (!ifs.eof())
{
ifs.read(&bar,sizeof(bar));
loc = ifs.tellg();
loc += bar.dwHeaderSize;
// four byte boundary padding
if ((loc % 4) != 0)
loc += 4 - (loc % 4);
ifs.seekg(loc,ios::beg);
}
ifs.close();
このコードは VS 2005 では正常に動作しましたが、VS 2008 Express では失敗します。私の知る限り、VS 2008 はコードがファイルの最後までシークした後でも eof() を返しません。何かが足りないのでしょうか?シーク位置がファイル サイズを超えているかどうかを確認する明示的なチェックを追加することでこの問題を修正しましたが、ifstream を正しく理解していることを確認したいと考えています。
解決
EOF フラグは、ファイルの終わりを超えて読み取ろうとした後にのみトリガーされます。
読む upto
ファイルの終わりはトリガーしません。
このため、ほとんどのコードは次のようになります。
while(ifs.read(&bar,sizeof(bar)))
{
// Do Stuff
}
read() の結果が EOF に達すると、ループに入ります。
read() の結果が EOF を超えた場合、ループには入りません。
- 注記:read() は、ファイルにゼロバイトが残っている場合にのみ EOF を通過します。それ以外の場合は、ファイルの最後まで読み取られます。したがって、ファイルに何かが残っている場合は常にループに入ります。
その理由は、読み取り結果 (戻り値) がストリームへの参照であるためです。ストリームがブール コンテキスト (if テスト式など) で使用される場合、そのようなコンテキストで使用できる型に変換されます。この変換の結果は、(他のいくつかのフラグに加えて) EOF フラグをテストし、EOF が true の場合は false と同等の値を返します。
注記:
この手法は、Bar クラスの演算子 << をオーバーロードすると、EOF を超えずにオブジェクトに必要なものを正確に読み取る必要があるため、より効果的に機能します。これにより、オブジェクトをファイルの最後まで正確に読み取らせることが容易になります。read に関して私が心配しているのは、read() が 10 バイトを必要としていて、ファイル内に 5 バイトしかない場合に何が起こるかということです。部分的に埋められたオブジェクトはどうなるでしょうか?
スタイルを引き続き使用したい場合、コードは次のようになります。
ifs.open("foo");
while (!ifs.eof())
{
ifs.read(&bar,sizeof(bar));
if (ifs.eof())
{ break;
}
// Do Stuff
}