Monthly Archives: August 2012

[Corona SDK] system.pathForFile 의 버그(?)

컨테이너 앱과 같이 컨텐츠를 다운로드 받아서 실행하는 형태에서는 각 컨텐츠마다 리소스가 달라서 파일의 존재 유무를 파악할 필요가 있습니다.

Corona API Docs: http://docs.coronalabs.com/api/library/system/pathForFile.html

최신 코로나 SDK API 문서에서 system.pathForFile()이라는 함수를 찾았습니다.
그런데 예제를 봤더니 이게 왠 일인가?

local path = system.pathForFile(  "data.txt", system.DocumentsDirectory )
local fhd = io.open( path )

-- Determine if file exists
if fhd then
	print( "File exists" )
	fhd.close()
else
	print( "File does not exist!" )
end

“왜 파일 유무를 확인하기 위해서 io.open( path )와 같이 성능을 떨어뜨릴 수 있는 api를 사용해야 할까?” 라는 의문이 들었습니다.

예제를 이용해서 존재하지 않는 파일을 열기 위해 다음과 같이 확인을 해봤습니다.

	path = system.pathForFile( "not_exist_file.png" )
	if (path) then   -- Determine if file exists
		if (myLabel) then
			myLabel.text = "File exists in " .. path
		else
			print( "File exists in " .. path )
		end
        else
		if (myLabel) then
			myLabel.text = "File not found"
		else
			print( "File not found" )
		end
	end

iOS에서는 “File not found” 가 출력이 되어 “역시 !” 라는 감탄사를 하려는 찰라 android에서는 “File exist in…”이 출력되는 것이었습니다.

결국 Corona Labs에 버그리포트(#16565)하고 안드로이드를 위해 회피코드를 다음과 같이 삽입했습니다.

	local myPlatform = system.getInfo( "platformName" )
	path = system.pathForFile( "not_exist_file.png" )
	if (path) then   -- Determine if file exists
		local fhd, isIOS
		if (myPlatform == "Android") then
			fhd = io.open( path )
		else
			isIOS = true
		end

		-- Determine if file exists
		if (fhd or isIOS) then
		       if (myLabel) then
			      myLabel.text = "File exists in " .. path
		       else
		   	      print( "File exists in " .. path )
		       end
                end
	end

결론적으로 App Pkg Bundle내의 파일 존재 유무에 대해서 iOS에서는 system.pathForFile()만으로 판단이 가능하지만 android에서는 io.open()으로 열어봐야 한다는 것입니다.

그럼 건투를 빕니다.

Update — 2012년 8월 21일 화요일 (8월 16일 수신)

your use of io.open is completely valid, and will not hurt performance.

The problem you are facing is that Android device’s don’t have a system.ResourceDirectory (folder). As clearly outlined here: http://docs.coronalabs.com/api/library/system/pathForFile.html

So for extra sanity it would be wise to check whether a file exists using io.open in conjunction with system.pathForFile. Also system.pathForFile doesn’t return nil if the parent directory is valid, so the same check on a file in the Documents directory would print the path, whether the file exists or not.

As you can see via the below example code:

local noFile = system.pathForFile("NonExistentFile.png", system.DocumentsDirectory )


local d = display.newText( noFile, 0, 0, 300, 480, nil, 18 )
d:setReferencePoint( display.TopCenterReferencePoint )
d.x, d.y = display.contentCenterX, display.contentCenterY - d.contentHeight * 0.5

Generally the accepted way to check for file existence with corona is like so:

local function doesFileExist( theFile, theDirectory )
	local filePath = system.pathForFile( theFile, theDirectory or system.DocumentsDirectory )
	local results = false
	        
	local file = io.open(filePath, "r")
	    
	--If the file exists, return true
	if file then
	    io.close(file)
	    results = true
	end
	 
	return results
end

--You can then check if a file exists like so:
if doesFileExist( "myFile.png", system.ResourceDirectory ) == true then
   --File exists
   print( "File found" )
else
   --File doesn't exist
   print( "File not found" )
end

2012년 8월 16일에 코로나 연구소로부터 온 내용에 따르면 io.open을 사용해도 성능에 전혀 상관이 없다고 합니다.
과연 그런지는 실제 확인을 아직 못해봤으나 다음 시간에는 꼭 실측을 해봐야겠습니다.

어쨌든 코로나 연구소의 전언에 따르면 io.open을 사용하는데 부담을 갖지 않으셔도 되겠습니다.