2012-03-06 5 views
7

C++プログラムでは、std :: ifstreamを使用して、ユーザー指定のファイルを開こうとしています。しかし、誤って実際にディレクトリであるファイル名を入力しましたが、open()しようとするとエラーは発生しませんでした。引数がディレクトリのときにIfstream open()がエラービットを設定しない

std::ifstream f; 
f.open(".."); 
if(!f.is_open() || !f.good() || f.bad() || f.fail()) { 
    std::cout << "error bit set on open" << std::endl; 
    return 1; 
} 

ここでエラーの兆候:

はここで、最小限の例です。私がgetline()を実行しようとすると、getline()はエラービットを正しく設定します。

std::string str; 
getline(f, str); 

if(f.eof()) std::cout << "getline set eofbit" << std::endl; 
else if(f.bad()) std::cout << "getline set badbit" << std::endl; 
else if(f.fail()) std::cout << "getline set failbit" << std::endl; 

"getline set badbit"が出力されます。これは妥当です。 >>演算子を使用するとアンダーフロー例外がスローされますが、これも問題ありません。

私の質問は、ユーザーが適切なファイル名ではなくディレクトリ名を入力したことをどのように検出することができたかです。それを行う方法はありますか?ストリームからのバイトの取得と削除は面倒でエラーが発生しやすいようです。

また、これはなぜですか?私はそれがプログラムの観点からは全く同じデータであることを理解していますが、私はOSが "やあ、これはディレクトリです"というようなメッセージを送ると仮定します。

+0

この動作はどのプラットフォームで発生していますか? –

+0

C++には「ディレクトリ」という概念はありません。プラットフォーム固有のライブラリ(PosixやWindowsなど)が必要です。 –

+0

ああ、Ubuntu 10.04、コンパイラはgcc 4.4.3です。 –

答えて

3

あなたのシステムが何であるかはわかりませんが、言うことは難しいですが、 filebuf::openは、システムレベルが開いているときにエラーが返されるのは です。私はUnixシステムで働いています。open() ディレクトリです。私は がオープンした後で読むことができるところで作業しました(少なくともローカルにマウントされたファイルシステムであれば)。

どうすればいいか:私が考えることのできることは、get の最初の文字を試してみることです。しかし、ファイルが であればこれは失敗します。だから、本当に解決策でもありません。システムレベル(QoIの観点からは )では、 システムでディレクトリを開くことが許可されている場合にfilebuf::openが実行されます。 (Unixではstat)というシステムレベルのコールを使用して、ファイルはディレクトリかどうか。 (競合状態があります:通常のファイルである を検出した瞬間から、開かれた瞬間に別のプロセス がファイルを削除してディレクトリを作成する可能性がありますが、おそらくは 、 )

+0

ああ、それはプラットフォーム固有のものなので、結局私は推測できました。説明ありがとう。はい、これはLinux上にあります(Ubuntu、Debianでも同じことが起こります)。私はちょうどそれが有効で読みやすいファイルストリームであることを保証しようとしているので、私はよりクリーンなソリューションを望んでいましたが、取得と削除は合理的です。依存関係とシステムコールは過度のようです。つまり、私はエラーで生きることができますが、それは奇妙に見えました。 –

+1

@SáT:ハードウェア上で使用されている基本的なファイルシステムに固有のものであると推測します(ディスクによって使用されるファイルシステムを選択できるOSもあります)。 –

+1

@LokiAstariそうだと思います。 IIRC(試してみてからしばらく時間がかかりました)、Solarisでは、ローカルにマウントされたディスク(UFS)で動作するディレクトリで 'open'しますが、ファイルシステムがNFSの場合はそうではありません。 –

関連する問題