none
How to detect if a file exists

    Question

  • I could have sworn that I saw code like this in one of the Build sessions:

               

    var f = await folder.GetFileAsync(fileName);
    if(f != null) {
     ....
    }
    

    But this code throws a FileNotFoundException if fileName doesn't exist.
    Can anyone point me to a clean (non-exception causing) way of finding out if a file exists?


    http://about.me/dmehers
    Thursday, September 22, 2011 9:39 PM

Answers

  • Currently the only way to check if a file exists is to catch the FileNotFoundException. As has been pointed out having an explicit check and the opening is a race condition and as such I don't expect there to be any file exists API's added. I believe the File IO team (I'm not on that team so I don't know for sure but this is what I've heard) is considering having this API return null instead of throwing if the file doesn't exist.


    Blog: http://weblogs.asp.net/whaggard
    • Marked as answer by DamianMehers Friday, September 23, 2011 6:28 AM
    Friday, September 23, 2011 3:43 AM

All replies

  • One of the ways to check if a file exists in the async model is to programmatically check for the result of the GetFileAsync task, like this:
    
    async Task YourFunction() {
        if (await DoesFileExistAsync(fileName))
        {
    		// file exists; code for happy path
    	}
    	else
    	{
    		// file does not exist
    	}
    }
     //The actual file retrieval logic
    async Task<bool> DoesFileExistAsync(string fileName) {
    	try {
    		await folder.GetFileAsync(fileName)
    		return true;
    	} catch {
    		return false;
    	}
    }
    


    Harini Kannan | Program Manager, XAML
    • Proposed as answer by Tran Van Tuan Thursday, June 07, 2012 1:35 PM
    Thursday, September 22, 2011 10:16 PM
  • Exceptions are actually the best way to deal with situations like this, otherwise you're just creating a subtle race condition. Imagine what happens if you check to see if a file exists, but then another process on the system deletes it (or creates it) before your application gets chance to do whatever it was about to do.

    If you instead just attempt the operation and deal with failure via exception you end up with the safest possible code. Raymond Chen actually wrote a couple of blogs on this anti-pattern (google for IsBadXXXPtr and you'll probably find them).

    Thursday, September 22, 2011 10:25 PM
  • OK thanks - I've been conditioned into thinking that Exceptions should be exceptional, since they are relatively expensive - in my case the file not existing is a perfectly normal condition that is likely to happen frequently.  I'm using the exception method, but I was convinced that I must be overlooking an obvious API somewhere.  I assumed that since  Windows 8 Metro style apps are isolated I can know that no-one else will touch the app's files.

     

    Damian


    http://about.me/dmehers

    • Edited by DamianMehers Thursday, September 22, 2011 10:43 PM
    Thursday, September 22, 2011 10:40 PM
  • Raymond's IsBadXXXPtr blog posts were really about an entirely different circumstance, where the function itself was hiding exceptions. Checking for file existence doesn't hide any exceptions, it just gives you the chance to avoid them if possible. Of course an exception may still be thrown and you have to be prepared to handle it, but that doesn't mean that checking for file existence is an anti-pattern.


    Moderator | MCTS .NET 2.0 Web Applications | My Blog: http://www.commongenius.com
    Thursday, September 22, 2011 10:53 PM
  • Exceptions should be exceptional; the problem is that there isn't much agreement on what constitutes "exceptional". My attitude is generally that exceptions should be thrown whenever the immediate caller cannot handle the error condition. Sometimes that means an exception is thrown and then caught within my application when it doesn't strictly have to be, which some people frown on and can lead to a less than ideal debugging experience. But I find that it leads to cleaner code with less error handling logic, which makes the code easier to understand.

    As far as the performance impact of exceptions, I think that depends on your circumstances. If you are opening a single file in response to a user action, just let the exception be thrown. You have to write a handler for it anyway, and that way you don't have to deal with the additional code to pre-check for existence. On the other hand, if you are operating on a large group of files, where there is the potential for a large number of exceptions to be thrown and caught, it might be worth the extra code to pre-check: the performance impact of a single exception isn't that significant, but a lot of them in a row can add up.


    Moderator | MCTS .NET 2.0 Web Applications | My Blog: http://www.commongenius.com
    Thursday, September 22, 2011 11:01 PM
  • In my particular case I'm fetching images from the web for a series of elements in a grid - if I have the image already downloaded then I want to use that, otherwise I fetch if from the web and save it to file, and then use it.

    The first time the user runs the app there may be thousands of elements, and so thousands of FileNoteFoundExceptions thrown.  The second time none (unless the user quit the app before they could all be downloaded).

    I'm currently setting the image from the file, and if a FileNotFound exception is thrown I do the download, and set the image from the file again.


    http://about.me/dmehers
    Thursday, September 22, 2011 11:08 PM
  • In that case, since there is the potential for a large number of exceptions to be thrown in a short period of time, and the delay caused by those exceptions could definitely be noticed by the user, I think it is worth checking for file existence ahead of time. Just remember to handle the possible exception as well.
    Moderator | MCTS .NET 2.0 Web Applications | My Blog: http://www.commongenius.com
    Thursday, September 22, 2011 11:31 PM
  • How do I check for file existence?  That was my original question :-)
    http://about.me/dmehers
    Thursday, September 22, 2011 11:43 PM
  • Currently the only way to check if a file exists is to catch the FileNotFoundException. As has been pointed out having an explicit check and the opening is a race condition and as such I don't expect there to be any file exists API's added. I believe the File IO team (I'm not on that team so I don't know for sure but this is what I've heard) is considering having this API return null instead of throwing if the file doesn't exist.


    Blog: http://weblogs.asp.net/whaggard
    • Marked as answer by DamianMehers Friday, September 23, 2011 6:28 AM
    Friday, September 23, 2011 3:43 AM
  • Wes,

    Returning null doesn't explain why the file couldn't open; and in scenarios such as Damian's, throwing an exception for every file that fails to open could be very expensive. It sounds like this is a significant regression in the file system API that needs to be addressed.


    Moderator | MCTS .NET 2.0 Web Applications | My Blog: http://www.commongenius.com
    Friday, September 23, 2011 2:10 PM
  • Hi,

    I am using Windows 8 Preview release. When I want to get instance of StorageFile using name of requested file I have got FileNofFoundException exception if file doesn't exist.

    Maybe someone knows answer for DamianMehers's question "How do I check for file existence? " in Windows 8 preview release?

    Thank you in advance!


    Saturday, June 02, 2012 2:23 PM
  • You just can't, because it's a question the OS can never reliably answer.

    Play through the scenario in your head:

    1. You ask the OS if a file exists
    2. You get a reply of true/false
    3. Before you have chance to do anything, some other process on the system creates/deletes the file in question
    4. Now you attempt to act on the true/false your app received, except it's already wrong and so your app's behaviour is wrong

    Fundamentally the only way you can avoid this is by actually attempting to do whatever it is you originally wanted to do and then handling the case where it fails. Since the API design does this by throwing an exception, you simply have to deal with it that way. The only way to avoid exceptions would be if the API were instead designed to respond in some different fashion, but that seems unlikely at this point.

    Sunday, June 03, 2012 11:29 AM
  • Wait... I'm calling you out on this one.  Here's what the System.IO.File.Exists documentation states:

    "The Exists method should not be used for path validation, this method merely checks if the file specified in path exists. Passing an invalid path to Exists returns false.
     
    Be aware that another process can potentially do something with the file in between the time you call the Exists method and perform another operation on the file, such as Delete.

    ...

    The Exists method returns false if any error occurs while trying to determine if the specified file exists. This can occur in situations that raise exceptions such as passing a file name with invalid characters or too many characters, a failing or missing disk, or if the caller does not have permission to read the file."

    This concern isn't new.  We've been using this for over a decade; so why the change, or rather, regression?

    The race condition excuse, to me, is just that.  It existed (no pun intended) in all versions of .NET and thousands upon thousands have utilized it, from what I can only assume, successfully without any race condition occuring. 

    Additionally, with regards to LocalStorage... it's local to the Application, right?  Who is the "multiple user" and why would the OS rip the rugs out from under you.  So you (the app) is in control.  Sure, multi-threaded or async actions could also cause this; however, that's up the the developer to handle.  That doesn't remove the desire (need) to have a familiar API.

    Are you suggesting that Microsoft has a ton of reports suggesting otherwise?

    Bottom line, it just feels dirty to have to rely on an exception for something so simple; not to mention the lack of something familiar for something that seems, not only common but, necessary.


    Cory Smith http://addressof.com

    Tuesday, June 05, 2012 11:31 PM
  • "..the File IO team ... is considering having this API return null instead of throwing if the file doesn't exist."

    This won't be changing. This design will stand for Win8.

    Chris

    Tuesday, June 05, 2012 11:51 PM
  • ... I'm currently setting the image from the file, and if a FileNotFound exception is thrown ...
    http://about.me/dmehers

    I'm trying to do something similar in C++, but I am not finding a definition for FileNotFoundExeption.  What namespace is that exception in?  I'm using the latest VS11 and C++.  All the docs I've found online suggest the FileNotFoundException should be in a System.IO package, but that's not present in C++, afaict.

    Thanks.

    Monday, June 11, 2012 7:27 PM
  • I had the same problem.

    I try to cache a lot of pictures on the PC from the web. If the pictures already exist want to do nothing.

    To acquire this, I create a file with the collisionoption GenerateUniqueName and check if the name is the same that I set. If not the file already exists, and I can delete the new file and return.

    file = await folder.CreateFileAsync(Path.GetFileName(path), Windows.Storage.CreationCollisionOption.GenerateUniqueName);
                        if (file.Name != Path.GetFileName(path))
                        {
                            await file.DeleteAsync();
                            return;
                        }
    That's a little bit ugly but it seems to be faster than catching 316 exceptions.
    • Proposed as answer by Loki Midgard Friday, September 14, 2012 1:27 PM
    Thursday, July 12, 2012 3:33 PM
  • Wes, you guys need to reconsider your position.  This is a bad API decision and MS is over-engineering their approach to this method call.  Yes, a race condition is present in a multithreaded application scenario BUT there is a clear and definite need to determine if a file exists without incurring the overhead of throwing an exception up the call stack.  This is isolated application storage -- the number of processes accessing the file is determined by the programmer and it is not the role of the API developer to optimize based on assumption of how invocation should occur.  For myself, as well as others on this thread, we desire a mechanism to validate the existence of a file to handle caching scenarios where threading is not an issue.
    Monday, July 23, 2012 12:15 AM
  • Hi,

    I have faced a problem from many days that, If I tried to open a file or get a file using WinRT api(java script) I usually got unhandled exceptions "the system can not find the file specified". Then I need to check whether it is existed or not before trying to open it. Then also I faced the same issue...

     So Finally I overcame this unhandled exception by checking the file existence, The file existence can be done by using

    getFilesAsync(). yes it will return total files in a folder then we can check that if our file is existed in the list of files returned by getFilesAsync(),If it is existed then Im opening that file or loading that file

    Hope it may help for you guys too..

    -NagendraVivek

    WebToGo Mobiles Internet Private Ltd.

    getFilesAsync()

     

    • Proposed as answer by Loki Midgard Friday, September 14, 2012 1:27 PM
    Friday, September 14, 2012 1:16 PM
  • All I want to check if the file exists at the time of checking. Whether another process just created it or deleted it, is not my concern. At the moment of checking if it exists (however, whenever it was conceived) it should return true, false otherwise. Define the existence of a file, however the designer wants it to be.

    There are many scenarios where we want to simply check the existence, preferably as fast as possible, instead of creating a task, wait for its completion, catch its exception at the .get() value, and then finally return a result. Take it to a debugger, and you will see how many complex concurrency code path it hops through when you call GetFileFromPathAsync() (the simplest of all). Someone can convince me that it is as fast as a simple check of file-existence on the file system - I have doubt.

    The code to write file existence in C++ is even more messy where I have to check on aTask.get() and cause the exception for the "does-not-exist" case. A humble question: has anyone posted anywhere C++ code for isFileExist() for MetroApp?

    I would be very grateful to see an authoritative answer from someone in the MS File/IO team developers/engineers take some trouble and tell us that this is how one should do isFileExist() in MetroApp in all 3 supported flavors (C#, C++, JS). 

    Yes, I intend to use isFileExist() in multi-threaded environment. Thanks,

    -User.


    sua

    • Proposed as answer by SL RU Saturday, January 26, 2013 1:57 PM
    Saturday, September 29, 2012 10:15 PM
  • // here is the C++ version
    
    task<bool> DoesFileExist(StorageFolder^ folder, String^ fileName)
    {
        return create_task(folder->GetFileAsync(fileName)).then([](task<StorageFile^> taskResult)
        {
            bool exists;
            try
            {
                taskResult.get();
                exists = true;
            }
            catch (COMException ^ex)
            {
                // ignore expected exception when the file does not exist
                if (ex->HResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
                {
                    exists = false;
                }
                else
                {
                    throw;
                }
            }
            return exists;
        });
    }
    
        // demonstrate use
        DoesFileExist(Windows::Storage::KnownFolders::PicturesLibrary, "Exists.txt").then([this](bool exists)
        {
            Output->Text += exists ? "exists\n" : "does not exist\n";
        });
    
        DoesFileExist(Windows::Storage::KnownFolders::PicturesLibrary, "Does not exist.txt").then([this](bool exists)
        {
            Output->Text += exists ? "exists\n" : "does not exist\n";
        });

    • Proposed as answer by Leonard Sunday, July 28, 2013 11:00 PM
    Monday, October 01, 2012 10:15 PM
  • public async void DoItAsync()
    {
        IReadOnlyList<StorageFile> storageFileList = await ApplicationData.Current.LocalFolder.GetFilesAsync();

        StorageFile storageFile = (from StorageFile s in storageFileList
                                   where s.Name == "myfile.txt"
                                   select s).FirstOrDefault();

        if (storageFile != null)
        {
           // Do it with your file here.
        }
        else
        {
            // File does not exist.
        }
    }

    Thursday, November 15, 2012 9:28 AM
  • This is too bad. The race condition has nothing to do with the FileExists API, but everything to do with the if(!FileExists()) CreateFile() pattern. There are perfectly legitimate cases for calling FileExists that to not involve opening or creating the file. For example, imagine a podcast app. Every downloaded podcast is stored in a local file; the filename is a hash of the URL. In the UI one would want to highlight the podcasts that were already downloaded. FileExists would be perfect for this application, and catching exceptions is not the proper approach, since the case is not "exceptional".

    Sunday, November 18, 2012 7:23 PM
  • Generally even with standard Win32 applications, File Exists tests are not very efficient. They trigger all the same Anti-Virus activity and are exactly as much work as opening the file to read in the first place.

    BAD:

    if File Exists
        if Open file succeeded
            Read file
        else
            Handle error
    else
       Handle error
       

    GOOD:

    if Open file succeeded
        Read file
    else
        Handle error (including possibly file not existing)

    That said, if you want a synchronous test for file existence in Windows Store apps, just use CreateFile2 with OPEN_ALWAYS

    Sunday, September 22, 2013 6:38 PM
  • Hi,

    I have tried the same logic for searching files and even if the files exists it throws the FileNotFoundException. 

                try
                {                                                                                                                              
                    int logoId = Int32.Parse((string)value);
                    logoImageFilePathName = string.Format("{0}\\{1}\\Logos\\Img\\{2}\\{3:0000}.png", installFolderPath, "images", LOGO_KIND_SMALL, logoId);
        
                    if (FileExistsAsync(installFolder, logoImageFilePathName).Result)
                    {
                        source = new BitmapImage(new Uri(logoImageFilePathName));
                        return source;
                    }

    }

    and it always throws the exception even if the file exists.

    Can anybody suggest what i should be doing ?

    Thanks,

    Tuesday, January 14, 2014 12:15 AM
  • i think with the latest versions of APIs those are fixed!

    i tried like this , if there file not exist then it will executing the error block woth out exceptions

     var fileName = "test.pdf";
    	        var localFolder = Windows.Storage.ApplicationData.current.localFolder;
    	        localFolder.getFileAsync(fileName).done(function (sampleFile) {
    	            img.src = URL.createObjectURL(sampleFile, { oneTimeOnly: true });
    	            document.getElementById(nextImg).appendChild(img);
    
    	        }, function (err) {
    	            log(err);
    	        });

    Monday, January 27, 2014 10:33 AM
  • Currently the only way to check if a file exists is to catch the FileNotFoundException. As has been pointed out having an explicit check and the opening is a race condition and as such I don't expect there to be any file exists API's added. I believe the File IO team (I'm not on that team so I don't know for sure but this is what I've heard) is considering having this API return null instead of throwing if the file doesn't exist.


    Blog: http://weblogs.asp.net/whaggard

    Fast forwarding 3 years, the API still throws a God forsaken exception.

    Now I have to wrap my code around this stupid decision instead of having a nice flow.

    Saturday, April 26, 2014 1:12 PM
  • Of course it does. If the behavior changed it would break existing apps.

    That said, you can rewind a year and a half and use http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.storage.storagefolder.trygetitemasync.aspx

    Saturday, April 26, 2014 4:48 PM
    Owner
  • Well too bad some one thought that wouldn't be necessary on windows phone.

    Sunday, April 27, 2014 10:46 AM
  • On Windows Phone, you can still use good old IsolatedStorageFile

    using ( var storage = IsolatedStorageFile.GetUserStoreForApplication () )
                    {
                        var exists = storage.FileExists (filename);
                        return exists;
                    }

    }


    Regards, Adarsha

    Friday, August 22, 2014 2:35 PM
  • On Windows Phone, you can still use good old IsolatedStorageFile

    using ( var storage = IsolatedStorageFile.GetUserStoreForApplication () )
                    {
                        var exists = storage.FileExists (filename);
                        return exists;
                    }

    }


    Regards, Adarsha


    In windows runtime apps there is currently no way of detecting if a file exists without throwing exception, or opening the file, creating a stream on it and checking the stream length. This is just a ridiculous oversight on behalf of the SDK team.
    Saturday, August 23, 2014 8:29 AM