CoronaSDK: How to know if a file exists?

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:

  1. system.ResourceDirectory
  2. system.DocumentsDirectory
  3. system.TemporaryDirectory

5 Comments

  1. 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.

  2. 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.

  3. 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.

  4. Thanks sir. Quite helpful that.
    Indeed if you want to check for a file in resource directory it is enough by calling system.pathforfile(name, system.resourcedirectory)

Leave a Reply

Your email address will not be published. Required fields are marked *