system.pathForFile() returns wrong folder for ResourceDirectory on OS X

BUG 40092 

Update

For those who run into this and want to get around it. you can simply do this:

-- As suggested by LERG -- local resourceRoot = system.pathForFile('main.lua', system.ResourceDirectory):sub(1, -9)

Summary

system.pathForFile(), should return the absolute path for a file or folder, but in the latest (and recent) versions of Corona SDK it fails to do so on OS X.

So far, I’ve tested three versions (2015.2570, 2015.2576, and 2015.2605).  In each case, I get different results for Windows vs OS X simulators when running this line of code:

What I Did

print( system.pathForFile( '', system.ResourceDirectory ) )

What I Expected

I expected this to print out the folder my app is in (i.e. absolute path of folder containing main.lua).

What I Got

  • Windows 7 - Works correctly: ‘x:\work\00_curentprojects\corona\casedetecterror’
  • OS X 10.10.2 - Fails every time.  Gives the folder the SDK  binary (or something like it) is in instead:
    • /Applications/CoronaSDK_2605/Corona Simulator.app/Contents/Resources/CoronaResources.bundle/Contents/Resources/

I’m still doing investigation into this, and will file a bug today, once I’m satisfied I’ve investigated enough.

Request: If you are running an OLD version of Corona on OS X, please try this single line of code.  If it prints the right directory, please post here and tell me the version number you are using.  This will help me determine when this changed.  

Lastly, I’m sure it used to work as I depended upon it for many of my personal and client tools.

Try it with 2511.  That’s the last stable release.  After that we can figure out if this intentional or if it’s regression bug.

Rob

@Rob,

I was away for a bit, but I’m back now and followed up on your advice.

2014.2511 also produces the wrong output for blank or ‘/’ paths.

It is worth noting, while this works (gives absolute path to main.lua),

print( system.pathForFile( "main.lua" ) ) -- returns expected absolute path

these both return the odd path I mentioned above.

print( system.pathForFile( "" ) ) -- returns path to binary? print( system.pathForFile( "/" ) ) -- returns path to binary?

Go ahead and file a bug report then. 

Rob

Try it with 2511.  That’s the last stable release.  After that we can figure out if this intentional or if it’s regression bug.

Rob

@Rob,

I was away for a bit, but I’m back now and followed up on your advice.

2014.2511 also produces the wrong output for blank or ‘/’ paths.

It is worth noting, while this works (gives absolute path to main.lua),

print( system.pathForFile( "main.lua" ) ) -- returns expected absolute path

these both return the odd path I mentioned above.

print( system.pathForFile( "" ) ) -- returns path to binary? print( system.pathForFile( "/" ) ) -- returns path to binary?

Go ahead and file a bug report then. 

Rob

Same problem to me.

The simple code below works fine on simulators, but fails on Android devices.

local strText = system.pathForFile("main.lua", system.ResourceDirectory) -- returns nil on Android devices local txtBox = display.newText(strText, display.contentCenterX, display.contentCenterY) -- on Android fails here

This code only generates a textbox, centered on screen, with the directory path text of the main.lua file.

On simulator, directory path returns correctly and code works fine.

On Android, system.pathForFile returns nil and then an error is raised because textbox text can’t be nil.

I’ve tested this code in CoronaSDK builds 2015.2646 and 2015.2692 (on Windows 8) and in 3 different  Android devices (Android version 4 or up).

I was about to post this the other day Ed. Thanks for reporting it.

This is not a bug. First off the syntax for system.pathForFile is 

system.pathForFile( filename [, baseDirectory] )

“filename” is not an optional parameter (it cannot be an empty string) since Corona tries to validate the file if it’s in the Resource Directory. You should get consistence results across all platforms if you provide a valid filename (per the limitations mentioned below).

The Resource directory holds your assets files and the lua files may not be there depending on the platform. system.pathForFile may give access on some platforms but on Android it depends on the type of files you are looking at.

The Android restrictions are listed here:
http://docs.coronalabs.com/api/library/system/pathForFile.html

The Resource directory is mainly used by our APIs where you can specify the baseDirectory (Image, audio, etc.). The system.pathForFile may give access to the files in this directory but it depends on the type of file and the platform you’re running on.

Thanks, Tom! You saved my day  :smiley:

Since the file name is required, can’t you use the name of a known file (at least in the case of system.ResourceDirectory) and strip the filename off from the results?  Main.lua won’t be there since it’s part of the compiled code, but you could leave a small data file, perhaps Icon.png or something to use to get a complete path to a file.

Rob

Another Corona engineer, Michael I believe, replied to a question in the Windows desktop beta forum and advised a user to get the path to the documents directory by passing nil as the first argument to pathForFile…

So there seems to be a differing opinion here? Even if it is unsupported, it would be nice to know why the behaviour changed on Mac only recently?

Edit: Link to Michael’s post: https://forums.coronalabs.com/topic/58409-systemdirectory-game-files/#entry302180

The documentation says either explicitly pass a file name or pass “nil” as the first parameter. Don’t pass an empty string. Don’t pass just a slash “/”. 

If this behavior does not work on a platform, then we will need a bug report.

Thanks

Rob

Got it, I’ll try that and see how it goes. I’ll open a bug report if needed.

Thanks Rob.

Hi,

I’m use this code for write time data, but i’m do not find “time.txt” on phone,where save this file(“time.txt”) ?

If this code do not  worke fore saving file(data), What functions can I use?

local path = system.pathForFile( “time.d.txt”, system.DocumentsDirectory )

local function updateTime()
    local time = os.date("*t")

    local saveData = time.hour
    local file = io.open( path, “a+” )
    file:write( saveData )
    io.close( file )

    local saveData = “:”
    local file = io.open( path, “a+” )
    file:write( saveData )
    io.close( file )

    local saveData = time.min
    local file = io.open( path, “a+” )
    file:write( saveData )
    io.close( file )

    local saveData = “:”
    local file = io.open( path, “a+” )
    file:write( saveData )
    io.close( file )

    local saveData = time.sec
    local file = io.open( path, “a+” )
    file:write( saveData )
    io.close( file )

end
local clockTimer = timer.performWithDelay( 1000, updateTime, -1 )

Help me please

Engineering has given this a thorough test and it works as we have it documented.  Let me clarify that part.

system.pathForFile() takes two parameters:  The file and the sandbox directory you want to use. If you just want the path to the sandbox, pass in nil, such as:

local path = system.pathForFile( nil, system.DocumentsDirectory )

Using “” or “/” or other combinations for the file may work on some platforms, but it’s not how we expect it to work.  There is one exception to this and it’s getting the path to system.ResourceDirectory on Android. Because there isn’t one (it’s just a zip file), calling:

local path = system.pathForFile( nil, system.ResourceDirectory )

on Android will return a nil since there is no such thing.  If you leave off the second parameter, it defaults to system.ResourceDirectory.

Hope this helps!

Rob

Same problem to me.

The simple code below works fine on simulators, but fails on Android devices.

local strText = system.pathForFile("main.lua", system.ResourceDirectory) -- returns nil on Android devices local txtBox = display.newText(strText, display.contentCenterX, display.contentCenterY) -- on Android fails here

This code only generates a textbox, centered on screen, with the directory path text of the main.lua file.

On simulator, directory path returns correctly and code works fine.

On Android, system.pathForFile returns nil and then an error is raised because textbox text can’t be nil.

I’ve tested this code in CoronaSDK builds 2015.2646 and 2015.2692 (on Windows 8) and in 3 different  Android devices (Android version 4 or up).

I was about to post this the other day Ed. Thanks for reporting it.

This is not a bug. First off the syntax for system.pathForFile is 

system.pathForFile( filename [, baseDirectory] )

“filename” is not an optional parameter (it cannot be an empty string) since Corona tries to validate the file if it’s in the Resource Directory. You should get consistence results across all platforms if you provide a valid filename (per the limitations mentioned below).

The Resource directory holds your assets files and the lua files may not be there depending on the platform. system.pathForFile may give access on some platforms but on Android it depends on the type of files you are looking at.

The Android restrictions are listed here:
http://docs.coronalabs.com/api/library/system/pathForFile.html

The Resource directory is mainly used by our APIs where you can specify the baseDirectory (Image, audio, etc.). The system.pathForFile may give access to the files in this directory but it depends on the type of file and the platform you’re running on.