Как создать временный файл с определенным расширением с .NET?

Мне нужно создать уникальный временный файл с расширением .csv.

То, что я делаю прямо сейчас, это

string filename = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv"); 

Однако это не гарантирует, что мой .csv-файл будет уникальным.

Я знаю, что вероятность того, что у меня столкнулась, очень низкая (особенно если вы считаете, что я не удаляю файлы .tmp), но этот код мне не подходит.

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

    Гарантировано быть (статистически) уникальным:

     string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv"; 

    (Процитировать из вики-статьи о вероятности столкновения:

    … годовой риск попадания meteorита оценивается как один шанс в 17 миллиардов [19], то есть вероятность составляет около 0,00000000006 (6 × 10-11), что эквивалентно шансам создания нескольких десятков триллионов UUID в год и с одним дубликатом. Другими словами, только после генерации 1 миллиарда UUID каждую секунду в течение следующих 100 лет вероятность создания всего одного дубликата составит около 50%. Вероятность одного дубликата будет составлять около 50%, если каждому человеку на земле принадлежит 600 миллионов UUID

    EDIT: Также см. Комментарии JaredPar.

    Попробуйте эту функцию …

     public static string GetTempFilePathWithExtension(string extension) { var path = Path.GetTempPath(); var fileName = Guid.NewGuid().ToString() + extension; return Path.Combine(path, fileName); } 

    Он вернет полный путь с расширением по вашему выбору.

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

     public static string GetTempFileName(string extension) { int attempt = 0; while (true) { string fileName = Path.GetRandomFileName(); fileName = Path.ChangeExtension(fileName, extension); fileName = Path.Combine(Path.GetTempPath(), fileName); try { using (new FileStream(fileName, FileMode.CreateNew)) { } return fileName; } catch (IOException ex) { if (++attempt == 10) throw new IOException("No unique temporary file name is available.", ex); } } } 

    Примечание: это работает как Path.GetTempFileName. Для сохранения имени файла создается пустой файл. Он делает 10 попыток, в случае коллизий, генерируемых Path.GetRandomFileName ();

    Вы также можете использовать System.CodeDom.Compiler.TempFileCollection .

     string tempDirectory = @"c:\\temp"; TempFileCollection coll = new TempFileCollection(tempDirectory, true); string filename = coll.AddExtension("txt", true); File.WriteAllText(Path.Combine(tempDirectory,filename),"Hello World"); 

    Здесь я использовал расширение txt, но вы можете указать, что хотите. Я также установил флаг keep true, чтобы временный файл сохранялся после использования. К сожалению, TempFileCollection создает один случайный файл на расширение. Если вам нужно больше файлов temp, вы можете создать несколько экземпляров TempFileCollection.

    Документация MSDN для GetTempFileName C ++ обсуждает вашу проблему и отвечает на нее:

    GetTempFileName не может гарантировать уникальность имени файла .

    Используются только младшие 16 бит параметра uUnique. Это ограничивает GetTempFileName максимум 65535 уникальными именами файлов, если параметры lpPathName и lpPrefixString остаются неизменными.

    Из-за алгоритма, используемого для генерации имен файлов, GetTempFileName может плохо работать при создании большого количества файлов с одним и тем же префиксом. В таких случаях рекомендуется создавать уникальные имена файлов на основе идентификаторов GUID .

    Почему бы не проверить, существует ли файл?

     string fileName; do { fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv"; } while (System.IO.File.Exists(fileName)); 

    Как насчет:

     Path.Combine(Path.GetTempPath(), DateTime.Now.Ticks.ToString() + "_" + Guid.NewGuid().ToString() + ".csv") 

    Очень маловероятно, что компьютер будет генерировать тот же Guid в тот же момент времени. Единственная слабость, которую я вижу здесь, – это влияние производительности DateTime.Now.Ticks.

    Вы также можете сделать следующее

     string filename = Path.ChangeExtension(Path.GetTempFileName(), ".csv"); 

    и это также работает так, как ожидалось

     string filename = Path.ChangeExtension(Path.GetTempPath() + Guid.NewGuid().ToString(), ".csv"); 

    На мой взгляд, большинство ответов, предложенных здесь как субоптимальные. Ближайший ближе – оригинал, предложенный первоначально Бранном.

    Имя файла Temp должно быть

    • уникальный
    • Бесконфликтный (еще не существует)
    • Atomic (создание имени и файла в одной операции)
    • Трудно угадать

    Из-за этих требований, это не богиня, чтобы программировать такого зверя по своему усмотрению. Умные люди, пишущие библиотеки IO, беспокоятся о таких вещах, как блокировка (при необходимости) и т. Д. Поэтому я не вижу необходимости переписывать System.IO.Path.GetTempFileName ().

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

     //Note that this already *creates* the file string filename1 = System.IO.Path.GetTempFileName() // Rename and move filename = filename.Replace(".tmp", ".csv"); File.Move(filename1 , filename); 

    Это может быть удобно для вас … Это создать темп. и вернуть его в виде строки в VB.NET.

    Легко конвертируется в C #:

     Public Function GetTempDirectory() As String Dim mpath As String Do mpath = System.IO.Path.Combine(System.IO.Path.GetTempPath, System.IO.Path.GetRandomFileName) Loop While System.IO.Directory.Exists(mpath) Or System.IO.File.Exists(mpath) System.IO.Directory.CreateDirectory(mpath) Return mpath End Function 

    Кажется, что это работает отлично для меня: он проверяет наличие файла и создает файл, чтобы убедиться, что он доступен для записи. Должен работать нормально, вы можете изменить его, чтобы напрямую вернуть FileStream (что обычно требуется для временного файла):

     private string GetTempFile(string fileExtension) { string temp = System.IO.Path.GetTempPath(); string res = string.Empty; while (true) { res = string.Format("{0}.{1}", Guid.NewGuid().ToString(), fileExtension); res = System.IO.Path.Combine(temp, res); if (!System.IO.File.Exists(res)) { try { System.IO.FileStream s = System.IO.File.Create(res); s.Close(); break; } catch (Exception) { } } } return res; } // GetTempFile 

    Это то, что я делаю:

     string tStamp = String.Format ("{0: yyyyMMdd.HHmmss}", DateTime.Now);
     строка ProcID = Process.GetCurrentProcess (). Id.ToString ();
     string tmpFolder = System.IO.Path.GetTempPath ();
     string outFile = tmpFolder + ProcID + "_" + tStamp + ".txt";
    

    Это простой, но эффективный способ генерации инкрементных имен файлов. Он будет выглядеть в текущем напрямую (вы можете легко указать, что где-то еще) и искать файлы с базовым YourApplicationName * .txt (снова вы можете легко изменить это). Он начнется с 0000, так что первым именем будет файл YourApplicationName0000.txt. если по какой-либо причине есть имена файлов с мусором между (а не цифрами) левой и правой частями, эти файлы будут проигнорированы в силу вызова tryparse.

      public static string CreateNewOutPutFile() { const string RemoveLeft = "YourApplicationName"; const string RemoveRight = ".txt"; const string searchString = RemoveLeft + "*" + RemoveRight; const string numberSpecifier = "0000"; int maxTempNdx = -1; string fileName; string [] Files = Directory.GetFiles(Directory.GetCurrentDirectory(), searchString); foreach( string file in Files) { fileName = Path.GetFileName(file); string stripped = fileName.Remove(fileName.Length - RemoveRight.Length, RemoveRight.Length).Remove(0, RemoveLeft.Length); if( int.TryParse(stripped,out int current) ) { if (current > maxTempNdx) maxTempNdx = current; } } maxTempNdx++; fileName = RemoveLeft + maxTempNdx.ToString(numberSpecifier) + RemoveRight; File.CreateText(fileName); // optional return fileName; } 

    Я думаю, вы должны попробовать это:

     string path = Path.GetRandomFileName(); path = Path.Combine(@"c:\temp", path); path = Path.ChangeExtension(path, ".tmp"); File.Create(path); 

    Он генерирует уникальное имя файла и создает файл с таким именем в указанном месте.

    Interesting Posts

    Ограничение количества символов в JTextField

    Подсчет уникальных / отдельных значений по группам в кадре данных

    Почему или не доступен ?

    Java – Лучший способ захватить ВСЕ строки между двумя строками? (регулярное выражение?)

    Укажите системное свойство для проекта Maven

    Передача массива в завернутую функцию как указатель + размер или диапазон

    Чтение проблем JPEG Метаданные (ориентация)

    Стратифицированная случайная выборка из кадра данных

    jQuery несколько событий для запуска одной и той же функции

    В чем проблема с размещением двух высокопроизводительных видеокарт на одном ПК?

    Горячие клавиши для Firefox 4?

    Mysql (mariadb) ERROR 1698 (28000): доступ запрещен для пользователя 'root' @ 'localhost'

    Есть ли команда linux, например mv, но с регулярным выражением?

    Как вызвать метод расширения с помощью отражения?

    Установите ширину разделителя «Позиция: фиксированный» относительно родительского div

    Давайте будем гением компьютера.