C#:如何通过添加数字来创建唯一的文件名?

Svi*_*ish 45 c# filenames unique

我想创建一个方法,它将文件名作为a string或a FileInfo,如果文件存在,则将增加的数字添加到文件名.但是不能完全理解如何以一种好的方式做到这一点.

例如,如果我有这个FileInfo

var file = new FileInfo(@"C:\file.ext");
Run Code Online (Sandbox Code Playgroud)

我想的方法给我一个新的FileInfo与C:\文件1.ext如果\ file.ext:C 存在,C:\文件2.ext如果C:\文件1.ext存在等.像这样的东西:

public FileInfo MakeUnique(FileInfo fileInfo)
{
    if(fileInfo == null)
        throw new ArgumentNullException("fileInfo");
    if(!fileInfo.Exists)
        return fileInfo;

    // Somehow construct new filename from the one we have, test it, 
    // then do it again if necessary.
}
Run Code Online (Sandbox Code Playgroud)

Meh*_*ari 50

public FileInfo MakeUnique(string path)
{            
    string dir = Path.GetDirectoryName(path);
    string fileName = Path.GetFileNameWithoutExtension(path);
    string fileExt = Path.GetExtension(path);

    for (int i = 1; ;++i) {
        if (!File.Exists(path))
            return new FileInfo(path);

        path = Path.Combine(dir, fileName + " " + i + fileExt);
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,这很容易受到其他答案中提到的竞争条件的影响.

  • @Sam:去写你的.我要睡了 ;) (12认同)
  • -1 - Dunno为什么这个答案有这么多的答案,它不会做出问题所要求的.它不会增加和替换文件名中的数字,而只是附加它(代码不会删除原始数字并将其替换为递增的数字). (11认同)

Svi*_*ish 30

这里有很多好建议.最后我用书面的方法马克回答不同的问题.重新格式化了一点,并添加了另一种方法,使其更容易"从外部"使用.结果如下:

private static string numberPattern = " ({0})";

public static string NextAvailableFilename(string path)
{
    // Short-cut if already available
    if (!File.Exists(path))
        return path;

    // If path has extension then insert the number pattern just before the extension and return next filename
    if (Path.HasExtension(path))
        return GetNextFilename(path.Insert(path.LastIndexOf(Path.GetExtension(path)), numberPattern));

    // Otherwise just append the pattern to the path and return next filename
    return GetNextFilename(path + numberPattern);
}

private static string GetNextFilename(string pattern)
{
    string tmp = string.Format(pattern, 1);
    if (tmp == pattern)
        throw new ArgumentException("The pattern must include an index place-holder", "pattern");

    if (!File.Exists(tmp))
        return tmp; // short-circuit if no matches

    int min = 1, max = 2; // min is inclusive, max is exclusive/untested

    while (File.Exists(string.Format(pattern, max)))
    {
        min = max;
        max *= 2;
    }

    while (max != min + 1)
    {
        int pivot = (max + min) / 2;
        if (File.Exists(string.Format(pattern, pivot)))
            min = pivot;
        else
            max = pivot;
    }

    return string.Format(pattern, max);
}
Run Code Online (Sandbox Code Playgroud)

到目前为止只进行了部分测试,但如果发现任何错误,将会更新.(Marc的代码效果很好!)如果您发现任何问题,请评论或编辑或者:)

  • @mdebeus阅读[我之前的评论](/sf/ask/75460241/?noredirect=1#comment22744335_1078898 )。如果您传入 `/tmp/myFile (1).txt`,那么这就是您会得到的。您应该传入 `/tmp/myFile.txt`。您传递您想要的名称,而不是现有的名称。 (2认同)
  • 这很棒。它为我提供了宝贵的见解,帮助我解决了我一直在解决的一个持续存在的设计缺陷。很有用。 (2认同)

Pie*_*let 18

不漂亮,但我有一段时间了:

private string getNextFileName(string fileName)
{
    string extension = Path.GetExtension(fileName);

    int i = 0;
    while (File.Exists(fileName))
    {
        if (i == 0)
            fileName = fileName.Replace(extension, "(" + ++i + ")" + extension);
        else
            fileName = fileName.Replace("(" + i + ")" + extension, "(" + ++i + ")" + extension);
    }

    return fileName;
}
Run Code Online (Sandbox Code Playgroud)

假设文件已经存在:

  • FILE.TXT
  • 文件(1).TXT
  • 文件(2).TXT

调用getNextFileName("File.txt")将返回"File(3).txt".

不是最有效的,因为它不使用二进制搜索,但对于小文件计数应该没问题.并且它不考虑竞争条件......


mga*_*911 12

如果检查文件是否存在太难,您可以随时在文件名中添加日期和时间以使其唯一:

FileName.YYYYMMDD.HHMMSS

如果有必要,甚至可以添加毫秒.

  • 如果订购*很重要,我绝对不会使用该日期格式...... (3认同)
  • 我成功地使用了这种技术.如果您创建的文件太快,则存在名称冲突的风险,但如果您知道您没有在几毫秒之内创建多个文件,那么它的效果很好. (2认同)
  • 您只需将其更改为YYYYMMDD.HHMMSS即可解决订购问题...... (2认同)

The*_*iot 5

如果格式不打扰你,那么你可以打电话:

try{
    string tempFile=System.IO.Path.GetTempFileName();
    string file=System.IO.Path.GetFileName(tempFile);
    //use file
    System.IO.File.Delete(tempFile);
}catch(IOException ioe){
  //handle 
}catch(FileIOPermission fp){
  //handle
}
Run Code Online (Sandbox Code Playgroud)

PS: - 请在使用之前在msdn上阅读更多相关信息.