简体   繁体   中英

C# move file and rename it, if it already exists

Background: I try to move a files to another location and want to rename them, if the file already exists. There are multiple processes that move files, with the same name, at the same time.

Normally I would use this approach:

string oldPath = @"smth1";
string newPath = @"smth";

if (File.Exists(newPath))
{
    filename = GetNewFilename(newPath);
}

//Problem, if file gets created here!!!*

File.Move(oldPath, newPath);

If I try to move the file and another process creates a file with the same name at the (*) moment, I get an IOException. Problem here is that there is no specific "FileAlreadyExistsException" that I can catch.

Am I missing something here, or is there any other way to solve this problem?

well you can handle all the possible errors that can be thrown if you want to be certain.

        try
        {
            File.Move(oldPath, newPath);
        }
        catch (ArgumentNullException)
        {
            //source of dest filename is null
        }
        catch(ArgumentException)
        {
            //source or dest file name/path not valid
        }
        catch(UnauthorizedAccessException)
        {
            //no permission
        }
        catch (DirectoryNotFoundException)
        {
            //dir not found
        }
        catch(PathTooLongException)
        {
            //path too long
        }
        catch(NotSupportedException)
        {
            //source or desk name is invalid format
        }
        catch (IOException)
        {
            if (File.Exists(newPath))
                //file exists
            else if (!File.Exists(oldPath))
                //old path does not exist
            else
                //Unknown error
        }

you can find all the possible ones on MSDN

Try to create the file at the beginning. If that doesn't work then you know that it already exists. If it does work then instead of moving the existing file, you would want to copy the old file into the new one and then delete the old one. That way you never have to lose hold of that new file that you created.

You can create a static field in your class and use lock statement to ensure that only one thread can create or rename a file and consequently other threads cannot create a file with the same name.

lock(_lockObject)
{
    //rename or create your file here
}

When using File.Move the IOException is thrown if the file already exists or if the original file isn't found; so there's that.

If you're getting this exception you need to have an algorithm in place, such as a counter appending on file name or similar, that reattempts it. I would add a measure of maximum attempts so that, in the event it just can't succeed for any reason, it will break out.

However, during this recursive attempt to move the file I suggest checking both that the source file exists and the destination file does not exist on each attempt. I also would only reattempt if you do indeed get the IOException specifically; with all other exceptions do other work accordingly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM