C #: Какой самый быстрый способ создать уникальное имя файла? - PullRequest
29 голосов
/ 21 октября 2009

Я видел несколько предложений по произвольному именованию файлов, включая использование

System.IO.Path.GetRandomFileName()

или используя

System.Guid

и добавление расширения файла.

Мой вопрос: Какой самый быстрый способ создания уникального имени файла?

Ответы [ 8 ]

36 голосов
/ 21 октября 2009

GUID будет чрезвычайно быстрым, , поскольку его реализация гарантирует, что Windows может генерировать не менее 16,384 GUID за промежуток времени в 100 наносекунд . (Как отмечали другие, спецификация не гарантирует, а только допускает. Однако генерация GUID действительно, очень быстрая. Действительно.) Вероятность коллизии в любой файловой системе в любой точке сети очень низкая. Достаточно безопасно, что, хотя было бы лучше всегда проверять, доступно ли это имя файла, в действительности вам даже не понадобится это делать.

Итак, вы смотрите на отсутствие операций ввода-вывода, кроме самого сохранения и <0,2 миллисекунды (на тестовой машине) для генерации самого имени. Довольно быстро. </p>

16 голосов
/ 21 октября 2009

Вы хотите System.IO.Path.GetTempFileName()

Я не могу сказать, действительно ли это самый быстрый или нет, но это правильный способ сделать это, что важнее.

5 голосов
/ 21 марта 2012

Ну, я пишу драйверы файловой системы в течение 20 лет и скажу, что Рекс прав. Генерирование guid происходит намного быстрее, поскольку требует гораздо меньших затрат, чем поиск уникального имени файла. GetTempFileName фактически создает файл, что означает, что он должен вызывать через весь стек драйверов файловой системы (кто знает, сколько будет вызовов, и переключиться в режим ядра). GetRandomFileName звучит так, как будто это быстрее, однако я бы доверял вызову GUID быть еще быстрее Люди не понимают, что даже проверка на наличие файла требует полного вызова через стек драйверов. Фактически это приводит к открытию, получению атрибутов и закрытию (что составляет не менее 3 вызовов в зависимости от уровня). На самом деле это минимум 20 вызовов функций и переход в режим ядра. Гарантия уникальности GUIDS достаточно для большинства целей.

Моя рекомендация - генерировать имя и создавать файл, только если он не существует. Если это так, сгенерируйте исключение и поймайте его, затем сгенерируйте новый guid и попробуйте снова. Таким образом, у вас нулевой шанс ошибок и вы можете спокойно спать по ночам.

Кстати, проверка на ошибки слишком преувеличена. Код должен быть спроектирован так, чтобы он падал, если допущения ошибочны, или перехватывал исключения и обрабатывал их тогда. Гораздо быстрее выдвигать, извлекать и обращаться к стеку исключений, чем каждый раз проверять каждую функцию на наличие ошибки.

3 голосов
/ 21 октября 2009

Если вы управляете местом назначения, в котором будут расположены файлы, и в него записывается только один процесс и поток, просто добавьте некоторое автоинкрементное число к базовому имени.

Если вы не контролируете пункт назначения или вам нужна многопоточная реализация, используйте GUID.

1 голос
/ 23 марта 2011

Если вы управляете каталогом, вы можете назвать свой файл на основе lastWriteTime:

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

Но вы должны проверить производительность этого кода: я думаю, создание DirectoryInfo не происходит бесплатно.

0 голосов
/ 02 марта 2018

Я надеюсь, что эта итеративная функция поможет кому-то создать уникальное имя файла.

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 голосов
/ 21 февраля 2011

Вы можете сделать что-то вроде:

file.MoveTo(deletedfilesdir + @"\" + f.Name + **DateTime.Now.ToFileTimeUtc()** + f.Extension);
0 голосов
/ 21 октября 2009

Используйте Int и увеличивайте его для каждого файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...