我已经实现了一种算法,该算法将为将保存在硬盘驱动器上的文件生成唯一的名称.我附加DateTime
:小时,分钟,秒和毫秒,但它仍然会生成重复的文件名,因为我一次上传多个文件.
为存储在硬盘驱动器上的文件生成唯一名称的最佳解决方案是什么,因此没有2个文件相同?
Uwe*_*eim 228
如果可读性无关紧要,请使用GUID.
例如:
var myUniqueFileName = string.Format(@"{0}.txt", Guid.NewGuid());
Run Code Online (Sandbox Code Playgroud)
或者更短:
var myUniqueFileName = $@"{Guid.NewGuid()}.txt";
Run Code Online (Sandbox Code Playgroud)
在我的程序中,我有时会尝试10次生成可读的名称("Image1.png".."Image10.png"),如果失败(因为文件已经存在),我会回到GUID.
更新:
最近,我还使用DateTime.Now.Ticks
了GUID代替GUID:
var myUniqueFileName = string.Format(@"{0}.txt", DateTime.Now.Ticks);
Run Code Online (Sandbox Code Playgroud)
要么
var myUniqueFileName = $@"{DateTime.Now.Ticks}.txt";
Run Code Online (Sandbox Code Playgroud)
对我来说,好处是,与GUID相比,这会生成更短,更"漂亮"的文件名.
请注意,在某些情况下(例如,在很短的时间内生成大量随机名称),这可能会产生非唯一值.
如果您想确保文件名是唯一的,即使将它们传输到其他计算机,也要坚持使用GUID.
KBB*_*ite 86
使用
Path.GetTempFileName()
Run Code Online (Sandbox Code Playgroud)
或使用新的GUID().
Ram*_*eef 73
System.IO.Path.GetRandomFileName()
Run Code Online (Sandbox Code Playgroud)
MSDN上的Path.GetRandomFileName().
Mas*_*Mas 53
如果文件名的可读性不重要,那么GUID就像许多人建议的那样.但是,我发现查看具有1000个GUID文件名的目录是非常艰巨的排序.所以我通常使用一个静态字符串的组合,它给文件名一些上下文信息,一个时间戳和GUID.
例如:
public string GenerateFileName(string context)
{
return context + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + Guid.NewGuid().ToString("N");
}
filename1 = GenerateFileName("MeasurementData");
filename2 = GenerateFileName("Image");
Run Code Online (Sandbox Code Playgroud)
这样,当我按文件名排序时,它将按上下文字符串自动对文件进行分组,并按时间戳排序.
请注意,Windows中的文件名限制为255个字符.
Mik*_*ain 20
这是一个算法,它根据提供的原始文件返回一个唯一可读的文件名.如果原始文件存在,则会逐渐尝试将索引附加到文件名,直到找到不存在的文件名.它将现有的文件名读入HashSet以检查冲突,因此它非常快(我的机器上每秒几百个文件名),它也是线程安全的,并且不会受到竞争条件的影响.
例如,如果您传递它test.txt
,它将尝试按以下顺序创建文件:
test.txt
test (2).txt
test (3).txt
Run Code Online (Sandbox Code Playgroud)
您可以指定最大尝试次数,也可以将其保留为默认值.
这是一个完整的例子:
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<string>(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();
}
}
Run Code Online (Sandbox Code Playgroud)
GetRandomFileName方法返回加密强大的随机字符串,可用作文件夹名称或文件名.与GetTempFileName不同,GetRandomFileName不会创建文件.当文件系统的安全性至关重要时,应该使用此方法而不是GetTempFileName.
例:
public static string GenerateFileName(string extension="")
{
return string.Concat(Path.GetRandomFileName().Replace(".", ""),
(!string.IsNullOrEmpty(extension)) ? (extension.StartsWith(".") ? extension : string.Concat(".", extension)) : "");
}
Run Code Online (Sandbox Code Playgroud)