web-dev-qa-db-ja.com

C#:一意のファイル名を生成する最も速い方法は何ですか?

私は使用を含め、ランダムにファイルに名前を付けることについていくつかの提案を見てきました

System.IO.Path.GetRandomFileName()

またはを使用して

System.Guid

ファイル拡張子を追加します。

私の質問は:一意のファイル名を生成する最も速い方法は何ですか?

29
Dan Esparza

A GUIDは非常に高速ですが、 これは、Windowsが100ナノ秒のタイムスパンで少なくとも16,384のGUIDSを生成できることを保証する実装であるためです。。 (他の人が指摘したように、仕様は保証せず、許可するだけです。しかし、GUID生成は本当に非常に高速です。本当に。)ネットワーク上のどこにでもファイルシステムが衝突する可能性とにかくそのファイル名が利用可能かどうかを常に確認するのがベストプラクティスですが、実際にはそれを行う必要さえないので十分安全です。

したがって、保存自体と、名前自体を生成するための(テストマシン上で)0.2ミリ秒未満のI/O操作はありません。かなり速い。

36
Rex M

あなたはSystem.IO.Path.GetTempFileName()が欲しい

最速かどうかは実際には言えませんが、これはの方法であり、より重要です。

16
Joel Coehoorn

さて、私は20年間ファイルシステムドライバーを作成しており、Rexは正しいと言っています。一意のファイル名を検索するよりもはるかに少ないオーバーヘッドで済むため、GUIDの生成ははるかに高速です。 GetTempFileNameは実際にファイルを作成します。つまり、ファイルシステムドライバースタック全体(呼び出しの数とカーネルモードへの切り替えを知っている)を介して呼び出す必要があります。GetRandomFileNameは高速に聞こえますが、GUID呼び出しをさらに高速化します。人々が気づいていないのは、ファイルの存在をテストする場合でも、ドライバースタックを介した完全な呼び出しが必要であることです。実際には、オープン、属性の取得、クローズ(レベルによっては少なくとも3回の呼び出し)が発生します。実際には、最低20の関数呼び出しとカーネルモードへの遷移です。一意性を保証するGUIDSは、ほとんどの目的に十分対応できます。

名前を生成し、存在しない場合にのみファイルを作成することをお勧めします。存在する場合は、例外をスローしてキャッチし、新しいGUIDを生成して再試行してください。そうすれば、エラーの可能性がゼロになり、夜は安眠できます。

余談ですが、エラーのチェックはやり過ぎです。コードは、仮定が間違っている場合にクラッシュするように、または例外をキャッチしてそれを処理するように設計する必要があります。すべての関数でエラーを毎回チェックするよりも、例外スタックでプッシュしてポップしてアドレスする方がはるかに高速です。

5
Jordan

ファイルの保存先を制御し、それに書き込むプロセスとスレッドが1つしかない場合は、ベース名に自動インクリメント番号を追加します。

宛先を制御しない場合、またはマルチスレッド実装が必要な場合は、GUIDを使用してください。

3
LBushkin

ディレクトリを制御する場合、lastWriteTimeに基づいてファイルに名前を付けることができます。

DirectoryInfo info = new DirectoryInfo(directoryPath);
long uniqueKey = info.LastWriteTime.Ticks+1L;
string filename = String.Format("file{0}.txt", key);

ただし、このコードのパフォーマンスを確認する必要があります。DirectoryInfoの作成は無料ではありません。

1
Stéphane

次のようなことができます:

file.MoveTo(deletedfilesdir + @"\" + f.Name + **DateTime.Now.ToFileTimeUtc()** + f.Extension);
0
Haroon

Intを使用して、ファイルごとに増分します。

0
Tom B

この自己反復関数が誰かが一意のファイル名を生成するのに役立つことを願っています。

public string getUniqueFileName(int i, string fullpath, string filename)
{
    string lstDir = fullpath.Substring(0, fullpath.LastIndexOf('\\'));
    string name = Path.GetFileName(fullpath);
    string path = fullpath;

    if (name != filename)
        path = Path.Combine(lstDir, filename);

    if (System.IO.File.Exists(path))
    {
        string ext = Path.GetExtension(name);
        name = Path.GetFileNameWithoutExtension(name);                
        i++;
        filename = getUniqueFileName(i, fullpath, name + "_" + i + ext);
    }

    return filename;
}
0
Bikuz