Search code examples
c#.netwpfuniquefilenames

Saving multiple files with same name


I'm working on a C# WPF application that does some data processing and outputs files in .csv format. What I am trying to achieve is that every time my program runs, it produces a test.csv output file, however when I run again with new data.. the new resultant file overwrites the old one. So I am trying to do something so that each created filename is unique. For example, test.csv, then test1.csv, test2.csv and so forth. I came up with the snippet below but I don't think the logic is correct and I can't figure out how to do this. Any help will be appreciated!

filename = "C:\\test.csv";
if (File.Exists(filename))
{
    int count = 0;
    for (int i = 0; i < 10; i++)
    {    
        filename = "C:\\test" + count + ".csv";
        count++;
    }
}

Solution

  • In your original code, you do the check only once. Try (note the while):

    filename = "C:\\test.csv";
    int count = 0;
    
    while (File.Exists(filename))
    {
        count++;
        filename = "C:\\test" + count + ".csv";                            
    }
    
    //save file goes here
    

    If you prefer, you can replace the while with this for loop:

    for(int count = 0; File.Exists(filename); count++)
        filename = "C:\\test" + count + ".csv";                            
    

    Update: As @eFloh indicated (see comments), there might be an issue when two instances of the above code are working simultaneously.

    This is because there's a slight window between the loop and the actual write-to-disk operation, so other process might just get in the middle and write a file with the same name, overwriting the file the other program is creating or causing errors.

    One possible solution is to write a special file to the directory when the loop is executing (and halt the execution is such file exists) to ensure no two running instances will conflict.

    Essentially, this file will signal the program that another program is executing this loop - so the other program shall wait until the other terminates.

    Explanation of the code below: The using block is trying to create a file called lock_file in the directory.

    • The FileMode.OpenOrCreate makes it possible to both open the file (if already exists) or create it (if it does not).
    • The FileAccess.Write make is possible to write the lock_file
    • The FileShare.Read makes the using wait until the fine is closed by other processes - so the program will wait when needed.
    • Finally, FileOptions.DeleteOnClose, makes the using block delete the lock_file on exit. This is extremely important because otherwise, the lock_file will stay there forever, rendering this block to wait forever to the deletion of this file.

    To wrap up (again, credit for this piece goes to @eFloh):

    using(new FileStream("C:\\lock_file", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, 4096, FileOptions.DeleteOnClose))
    {
        //loop and saving goes here
    }