C#: How would you make a unique filename by adding a number?

前端 未结 18 675
没有蜡笔的小新
没有蜡笔的小新 2020-11-27 11:46

I would like to create a method which takes either a filename as a string or a FileInfo and adds an incremented number to the filename if the file

相关标签:
18条回答
  • 2020-11-27 11:57

    Not pretty, but I've had this for a while :

    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;
    }
    

    Assuming the files already exist:

    • File.txt
    • File(1).txt
    • File(2).txt

    the call getNextFileName("File.txt") will return "File(3).txt".

    Not the most efficient because it doesn't use binary search, but should be ok for small file count. And it doesn't take race condition into account...

    0 讨论(0)
  • 2020-11-27 11:57

    Insert a new GUID into the file name.

    0 讨论(0)
  • 2020-11-27 11:58

    The idea is to get a list of the existing files, parse out the numbers, then make the next highest one.

    Note: This is vulnerable to race conditions, so if you have more than one thread creating these files, be careful.

    Note 2: This is untested.

    public static FileInfo GetNextUniqueFile(string path)
    {
        //if the given file doesn't exist, we're done
        if(!File.Exists(path))
            return new FileInfo(path);
    
        //split the path into parts
        string dirName = Path.GetDirectoryName(path);
        string fileName = Path.GetFileNameWithoutExtension(path);
        string fileExt = Path.GetExtension(path);
    
        //get the directory
        DirectoryInfo dir = new DirectoryInfo(dir);
    
        //get the list of existing files for this name and extension
        var existingFiles = dir.GetFiles(Path.ChangeExtension(fileName + " *", fileExt);
    
        //get the number strings from the existing files
        var NumberStrings = from file in existingFiles
                            select Path.GetFileNameWithoutExtension(file.Name)
                                .Remove(0, fileName.Length /*we remove the space too*/);
    
        //find the highest existing number
        int highestNumber = 0;
    
        foreach(var numberString in NumberStrings)
        {
            int tempNum;
            if(Int32.TryParse(numberString, out tempnum) && tempNum > highestNumber)
                highestNumber = tempNum;
        }
    
        //make the new FileInfo object
        string newFileName = fileName + " " + (highestNumber + 1).ToString();
        newFileName = Path.ChangeExtension(fileName, fileExt);
    
        return new FileInfo(Path.Combine(dirName, newFileName));
    }
    
    0 讨论(0)
  • 2020-11-27 11:59

    This method will add a index to existing file if needed:

    If the file exist, find the position of the last underscore. If the content after the underscore is a number, increase this number. otherwise add first index. repeat until unused file name found.

    static public string AddIndexToFileNameIfNeeded(string sFileNameWithPath)
    {
        string sFileNameWithIndex = sFileNameWithPath;
    
        while (File.Exists(sFileNameWithIndex)) // run in while scoop so if after adding an index the the file name the new file name exist, run again until find a unused file name
        { // File exist, need to add index
    
            string sFilePath = Path.GetDirectoryName(sFileNameWithIndex);
            string sFileName = Path.GetFileNameWithoutExtension(sFileNameWithIndex);
            string sFileExtension = Path.GetExtension(sFileNameWithIndex);
    
            if (sFileName.Contains('_'))
            { // Need to increase the existing index by one or add first index
    
                int iIndexOfUnderscore = sFileName.LastIndexOf('_');
                string sContentAfterUnderscore = sFileName.Substring(iIndexOfUnderscore + 1);
    
                // check if content after last underscore is a number, if so increase index by one, if not add the number _01
                int iCurrentIndex;
                bool bIsContentAfterLastUnderscoreIsNumber = int.TryParse(sContentAfterUnderscore, out iCurrentIndex);
                if (bIsContentAfterLastUnderscoreIsNumber)
                {
                    iCurrentIndex++;
                    string sContentBeforUnderscore = sFileName.Substring(0, iIndexOfUnderscore);
    
                    sFileName = sContentBeforUnderscore + "_" + iCurrentIndex.ToString("000");
                    sFileNameWithIndex = sFilePath + "\\" + sFileName + sFileExtension;
                }
                else
                {
                    sFileNameWithIndex = sFilePath + "\\" + sFileName + "_001" + sFileExtension;
                }
            }
            else
            { // No underscore in file name. Simple add first index
                sFileNameWithIndex = sFilePath + "\\" + sFileName + "_001" + sFileExtension;
            }
        }
    
        return sFileNameWithIndex;
    }
    
    0 讨论(0)
  • 2020-11-27 12:00

    Take a look at the methods in the Path class, specifically Path.GetFileNameWithoutExtension(), and Path.GetExtension().

    You may even find Path.GetRandomFileName() useful!

    Edit:

    In the past, I've used the technique of attempting to write the file (with my desired name), and then using the above functions to create a new name if an appropriate IOException is thrown, repeating until successful.

    0 讨论(0)
  • 2020-11-27 12:01

    If checking if the file exists is too hard you can always just add a date and time to the file name to make it unique:

    FileName.YYYYMMDD.HHMMSS

    Maybe even add milliseconds if necessary.

    0 讨论(0)
提交回复
热议问题