I have implemented an algorithm that will generate unique names for files that will save on hard drive. I\'m appending DateTime: Hours,Minutes,Second an
Here's an algorithm that returns a unique readable filename based on the original supplied. If the original file exists, it incrementally tries to append an index to the filename until it finds one that doesn't exist. It reads the existing filenames into a HashSet to check for collisions so it's pretty quick (a few hundred filenames per second on my machine), it's thread safe too, and doesn't suffer from race conditions.
For example, if you pass it test.txt, it will attempt to create files in this order:
test.txt
test (2).txt
test (3).txt
etc. You can specify the maximum attempts or just leave it at the default.
Here's a complete example:
class Program
{
static FileStream CreateFileWithUniqueName(string folder, string fileName,
int maxAttempts = 1024)
{
// get filename base and extension
var fileBase = Path.GetFileNameWithoutExtension(fileName);
var ext = Path.GetExtension(fileName);
// build hash set of filenames for performance
var files = new HashSet(Directory.GetFiles(folder));
for (var index = 0; index < maxAttempts; index++)
{
// first try with the original filename, else try incrementally adding an index
var name = (index == 0)
? fileName
: String.Format("{0} ({1}){2}", fileBase, index, ext);
// check if exists
var fullPath = Path.Combine(folder, name);
if(files.Contains(fullPath))
continue;
// try to create the file
try
{
return new FileStream(fullPath, FileMode.CreateNew, FileAccess.Write);
}
catch (DirectoryNotFoundException) { throw; }
catch (DriveNotFoundException) { throw; }
catch (IOException)
{
// Will occur if another thread created a file with this
// name since we created the HashSet. Ignore this and just
// try with the next filename.
}
}
throw new Exception("Could not create unique filename in " + maxAttempts + " attempts");
}
static void Main(string[] args)
{
for (var i = 0; i < 500; i++)
{
using (var stream = CreateFileWithUniqueName(@"c:\temp\", "test.txt"))
{
Console.WriteLine("Created \"" + stream.Name + "\"");
}
}
Console.ReadKey();
}
}