Update: Dejay was correct, you have to try and open the file to know for sure if it’s there or not.
Want to know if a file exists before you use it?
Lately, I’ve been wanting something a little more dynamic in my projects for opening various Scenes (think Director, but not). I needed a way of looking to see if a file existed or not before I tried to load it up. Here’s the result:
function fileExists(fileName, base) assert(fileName, "fileName is missing") local base = base or system.ResourceDirectory local filePath = system.pathForFile( fileName, base ) local exists = false if (filePath) then -- file may exist. won't know until you open it local fileHandle = io.open( filePath, "r" ) if (fileHandle) then -- nil if no file found exists = true io.close(fileHandle) end end return(exists) end
Typical usage:
if fileExists("myGame.lua") then -- do something wonderful end
If the file does not exist, the CoronaSDK library function system.pathForFile() returns nil. It also returns a Warning in the console, which can be safely ignored.
By default it checks your app’s asset directory (system.ResourceDirectory), however, if you’d like to check if a file you created exists you can pass in an alternative base path like so:
if fileExists("some_file.txt", system.DocumentsDirectory) then
-- do something wonderful
end
The three valid options for base path are:
Isn’t it true that this approach won’t work for system.DocumentsDirectory and system.TemporaryDirectory? My understand is that because those directories are read/write, system.pathForFile will return true even if the file doesn’t exist, as long as the file COULD be created in those directories.
There are a few optimizations you could make to your code. First, system.pathForFile already uses system.ResourceDirectory as a default, so there’s no need to invoke “local base = base or system.ResourceDirectory”. Also, if base is set to system.ResourceDirectory, there’s no need to check to see if the file exists, because pathForFile already tells you that with read-only directories.
Thanks Dejay.
You’re right. I don’t need to do the “local base = base or …”, but I find it makes it easier for me to read later. I don’t have to know the defaults for pathForFile.
Also, if pathForFile returns nil (which it does for readonly directories), the code already exits without checking any further on Line 7.
Cheers.