Search code examples
iosobjective-cnsdatansfilemanager

Rename a file if file already exists


What is the best way in objective-c to rename a file if a file with a same name exists.

Ideally, I would like to name untitled.png to untitled-1.png if a file named untitled.png already exists.

I have included my solution below as an answer, but I think there should be a better way (built-in function) to do it.

My solution is not thread-safe, and susceptible to race conditions.


Solution

  • The following function returns the next available filename:

        //returns next available unique filename (with suffix appended)
    - (NSString*) getNextAvailableFileName:(NSString*)filePath suffix:(NSString*)suffix
    {   
    
        NSFileManager* fm = [NSFileManager defaultManager];
    
        if ([fm fileExistsAtPath:[NSString stringWithFormat:@"%@.%@",filePath,suffix]]) {
            int maxIterations = 999;
            for (int numDuplicates = 1; numDuplicates < maxIterations; numDuplicates++)
            {
                NSString* testPath = [NSString stringWithFormat:@"%@-%d.%@",filePath,numDuplicates,suffix];
                if (![fm fileExistsAtPath:testPath])
                {
                    return testPath;
                }
            }
        }
    
        return [NSString stringWithFormat:@"%@.%@",filePath,suffix];
    }
    

    An example calling function is as follows:

        //See" http://stackoverflow.com/questions/1269214/how-to-save-an-image-that-is-returned-by-uiimagepickerview-controller
    
        // Get the image from the result
        UIImage* image = [info valueForKey:@"UIImagePickerControllerOriginalImage"];
    
        // Get the data for the image as a PNG
        NSData* imageData = UIImagePNGRepresentation(image);
    
        // Give a name to the file
        NSString* imageName = @"image";
        NSString* suffix = @"png";
    
    
        // Now we get the full path to the file
        NSString* filePath = [currentDirectory stringByAppendingPathComponent:imageName];
    
        //If file already exists, append unique suffix to file name
        NSString* fullPathToFile = [self getNextAvailableFileName:filePath suffix:suffix];
    
        // and then we write it out
        [imageData writeToFile:fullPathToFile atomically:NO];