2011-01-23 24 views
0

OK、ゲームを書いているので、このゲームにはインタラクティブな設定メニューがあります。私がしたいのは、ファイルが存在しない場合はファイルに書き込み、そうであればファイルから読み込み、ファイルに指定された設定を適用し、ユーザーが設定を変更することを選択した場合はユーザーの新しい設定で上書きします。だから、この(擬似コード)のようなものになるだろう:fopenの第二引数

if (file does not exist) 
    write_defaults 
open settings 
read from file 
apply settings specified in file 
while (user is changing settings) 
    if (user is done) break 
write new settings to file 
apply new settings 

は、今私は、関数fopenの第二引数のために何を使うのでしょうか?私は "r +"と "w +"の両方を試しましたが、両方で問題がありました。

+1

どのような問題がありましたか? – Davidann

答えて

0

"r+"を使用すると、最初の試行で正しくなります。ファイルが存在しないために失敗した場合は、"w+"で再試行してください。これにより、更新用のファイルが開かれますが、ファイルが既に存在する場合はファイルが壊れません。

しかし、これは、TOCTOU(チェックの時間、使用時間)の脆弱性があるという意味では最適ではありません。ファイルがオープン失敗の間に作成された場合、でのオープンに成功しました。ファイルは失われます。

あなたはPOSIX機能へのアクセスを持っている場合は、open()代わりのfopen()は、ファイルストリームにファイル記述子を変換するfdopen()に続く、1つの原子の試みで正しく仕事をするために使用することができます。

FILE *carefully_open(const char *file) 
{ 
    int fd = open(file, O_RDWR | O_CREAT, 0644); 
    FILE *fp = 0; 

    if (fd >= 0) 
     fp = fdopen(fd, "r+"); 
    if (fd >= 0 && fp == 0) 
     close(fd); 
    return fp; 
} 

これは、壊れたシンボリックリンクを介してファイルを作成するという欠点があります。 O_EXCLフラグで回避することはできますが、ファイルが存在する場合はオープンに失敗します。結局、open()への2回の呼び出しを行います.1つはO_RDRWで、もう1つはO_RDRW | O_CREAT | O_EXCLで、壊れたsymlnksに対して安全です。

(カレントディレクトリにはファイルpqrがない場合は?壊れたシンボリックリンクは何である、ln -s ./pqr xyzxyzが示さopen()コールでファイル「PQR」を作成することにより、「固定」されます壊れたシンボリックリンクであることを意味します。)

どのような問題がありましたか?

2

書き込み操作には"w"と開き、何らかのランダムアクセスを同時に行う読み書き操作をしていない限り、読み取り操作には"r"と再オープンします。

テキストではなく生のバイナリデータを操作する場合は、@stefanが以下のコメントで言及しているように、"rb"または"wb"が必要です。

+1

はい、これはfopenで必要以上にファイルを開いたままにしておくべき正しい方法です。オープン - 読み取り - クローズ。オープン - ライト - クローズ。また、書き込むデータに応じて、bを追加する必要があります。 – stefan

+0

@stefan:良い点。私はそれを私の答えに加えました。 –

+0

OK、私はそれを試みます。ありがとう。 – Babkock

0

"r +"でファイルを開くだけです。返されたポインタをチェックし、ポインタがNULLでない場合は、ファイルから設定を読み込みます。その後、ファイルに書き込みます。