5

特定のディレクトリの「foo.txt」に書き込みたいとします。「foo.txt」が既に存在する場合は、「foo-1.txt」に書き込みます。

この質問に答えようとするいくつかのコード スニペットがありますが、どれも満足のいくものではありません。たとえば、CocoaDev のこのソリューションでは、NSFileManager を使用してパスが存在するかどうかをテストし、安全なパスを作成します。ただし、これにより、パスの取得とパスへの書き込みの間に明らかな競合状態が発生します。アトミックな書き込みを試み、失敗した場合は数値サフィックスをループする方が安全です。

がんばれ!

4

3 に答える 3

1
int fd;
uint32_t counter;
char filename[1024]; // obviously unsafe

sprintf(filename, "foo.txt");
if( (fd = open(filename, O_CREAT | O_EXCL | O_EXLOCK, 0644)) == -1 && errno == EEXIST ) 
{
    for( counter = 1; counter < UINT32_MAX; counter++ ) {
      sprintf(filename, "foo-%u.txt", counter);
      if( (fd = open(filename, O_CREAT | O_EXCL | O_EXLOCK, 0644)) == -1 && errno == EEXIST )
        continue;
      else
        break;
    }
}

if( fd == -1 && counter == UINT32_MAX ) {
    fprintf(stderr, "too many foo-files\n");
} else if( fd == -1 ) {
    fprintf(stderr, "could not open file: %s\n", strerror(errno));
}

// otherwise fd is an open file with an atomically unique name and an
// exclusive lock.
于 2009-04-21T02:25:22.247 に答える
1

どうですか:

  1. 衝突のリスクがないことがわかっている一時ディレクトリにファイルを書き込みます
  2. NSFileManager を使用して、ファイルを目的の場所に移動します
  3. ファイルが既に存在するためにステップ 3 が失敗した場合は、数値サフィックスを追加/インクリメントして、ステップ 2 を繰り返します。

基本的に、Cocoa のアトミック ファイル書き込み処理を再作成しますが、一意のファイル名を保証する機能を追加します。このアプローチの大きな利点は、電源が切れたり、書き込み中にアプリがクラッシュしたりした場合、半分完成したファイルが tmp フォルダーに隠され、システムによって削除されることです。ユーザーが試して作業するために残されていません。

于 2009-04-21T09:06:54.013 に答える
1

およびオプションを指定してopenシステム コールを使用します。ファイルがまだ存在しない場合は、ファイルを作成して開き、ファイル記述子を返します。存在する場合は失敗し、 に設定されます。O_EXCLO_CREATopenopenerrnoEEXIST

そこから、ファイル記述子を返すか、ファイル名が長すぎるまでファイル名をインクリメントしようとするループを構築する方法は明らかです。errno後者の点では、いつopen失敗するかを確認してくださいENAMETOOLONG

于 2009-04-21T02:09:59.803 に答える