6

Recently I got the exception:

Message:
System.IO.IOException: The file 'C:\Windows\TEMP\635568456627146499.xlsx' already exists.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

This was the result of the following code I used for generating file names:

Path.Combine(Path.GetTempPath(), DateTime.Now.Ticks + ".xlsx");

After realising that it is possible to create two files in one Tick, I changed the code to:

Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".xlsx");

But I am still wondering what is the probability of the above exception in the new case?

gyosifov
  • 3,193
  • 4
  • 25
  • 41
  • Did you read the documentation for `GetRandomFileName`? What does it say? – Jonathon Reinhart Jan 14 '15 at 14:45
  • Not bloody likely at all. Still nice to gracefully handle the situation and keep getting new ones until you find one that doesn't already exist. –  Jan 14 '15 at 14:45
  • 5
    Or use Path.GetTempFileName() – Matthew Watson Jan 14 '15 at 14:46
  • Or check if that file exists before saving – Vsevolod Goloviznin Jan 14 '15 at 14:47
  • Also, how many files are you creating? Is this on a webserver? In general you should avoid using random path creation followed by open as it has a time-of-check to time-of-open race condition. There should be an API to return you a randomly-named open file. – Jonathon Reinhart Jan 14 '15 at 14:48
  • In the documentation it says: "The GetRandomFileName method returns a cryptographically strong, random string that can be used as either a folder name or a file name.", but probability is not mentioned @JonathonReinhart – gyosifov Jan 14 '15 at 14:48
  • "cryptographically strong" means, for all intents and purposes, **impossible**. – Jonathon Reinhart Jan 14 '15 at 14:50
  • @JonathonReinhart it is used for a OpenXml library I write (so it could be used in server apps) – gyosifov Jan 14 '15 at 14:50
  • 1
    I don't know the probability but `GetRandomFileName` simply uses `RNGCryptoServiceProvider` to create the filename or filename which already returned by `GetRandomFileName`. So clearly you can get existing file names. You need to handle the situation yourself. – Sriram Sakthivel Jan 14 '15 at 14:50
  • 4
    `Path.GetTempFileName` return an unique file name using the Win32 API GetTempFileName requestesting the creation of an unique file name. The Win32 API creates the file with a zero length and release the handle. So you don't fall in concurrency scenarios – Steve Jan 14 '15 at 14:51

4 Answers4

13

Internally, GetRandomFileName uses RNGCryptoServiceProvider to generate 11-character (name:8+ext:3) string. The string represents a base-32 encoded number, so the total number of possible strings is 3211 or 255.

Assuming uniform distribution, the chances of making a duplicate are about 2-55, or 1 in 36 quadrillion. That's pretty low: for comparison, your chances of winning NY lotto are roughly one million times higher.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

The probability of getting duplicate names with GetRandomFileName are really low, but if you look at it source here, you see that they don't check if the name is duplicate (They can't because you can't tell the path where this file should be created)

Instead the Path.GetTempFileName return an unique file name inside the Temp directory.
(So removing also the need to build the temp path in your code)
GetTempFileName uses the Win32 API GetTempFileName requesting the creation of an unique file name.
The Win32 API creates the file with a zero length and release the handle. So you don't fall in concurrency scenarios. Better use this one.

Steve
  • 213,761
  • 22
  • 232
  • 286
1

GetRandomFileName() returns 8.3 char string. This is 11 characters that can vary. Assuming it contains only letters and digits, this gives us an "alphabet" of 36 characters. So the number of variations is least 36^11, which makes the probability of above exception extremely low.

andreycha
  • 383
  • 4
  • 22
0

I would like to put my answer in comment area rather than here, but I don't have enough reputation to add comment.

For your first snippet, I think you can precheck if file exists or not.

For the second one, code will generate random name but random means you still have tiny teeny possibility to get the exception....but I don't think you need worry about this. Existence check will help.

Windtalker
  • 776
  • 4
  • 13
  • 23