os module to save to user's directory

Monkey Targets Forums/Desktop/os module to save to user's directory

jjsonick(Posted 2013) [#1]
Two of my major needs for monkey glfw, in-app fullscreen/windowed switching, and in-app resolution changes, look like they're addressed in v72a thanks to Mark and Skn3's work - hurrah!

My third glfw must-have is the ability to read/write files in the "approved" user directories in Windows and OS X. It's looking like this may be possible via the os module and environment variables.

The following seems to work in OS 10.7.5, Windows 7 and Windows Vista SP2 for me, and I can verify that test.dat is showin up in the right place:

Import mojo
Import os
Import brl


Class MyApp Extends App
	Field userDir:String
	Field fileSavePath:String
	Field configFilePath:String
	Field theInt:Int
	
	
	Method OnCreate()
	
		SetUpdateRate 30
		
		'USER DIRECTORY FOR SAVE FILES
		
		'-----------------------
		
		'Get user data path
		#If TARGET="glfw" Then
			
		'Construct this app's data paths
			If HostOS() = "macos"
				userDir = GetEnv("HOME")
				fileSavePath = userDir + "/Library/Application Support/MyFileTestApp"
				configFilePath = fileSavePath + "/test.dat"
			Elseif HostOS() = "winnt"
				userDir = GetEnv("APPDATA")
				fileSavePath = userDir + "\MyFileTestApp"
				configFilePath = fileSavePath + "\test.dat"
			Endif
			Print "filesave directory is :" + fileSavePath	
			Print "config file path is :" + configFilePath
			
		'See if directory exists, if not, create it
		'os.monkey has no DirExists function, so instead check for existence of default file
		'if default file not there, create directory and create default file
			Local file:=FileStream.Open(configFilePath,"r") 
			If Not file
				' Create New directory
				CreateDir(fileSavePath)	
				' Create blank file
				Local nfile:=FileStream.Open(configFilePath,"w")
				nfile.WriteInt 0
				nfile.Close
			Else file.Close
			Endif
		#Endif
		
    End
		
	Method OnUpdate()
	
			If KeyHit(KEY_LEFT) theInt -=1 
			
			If KeyHit(KEY_RIGHT) theInt +=1			
				
			If KeyHit(KEY_L)
				Print "attempting to open file"
				Local file:=FileStream.Open(configFilePath,"r")
				If Not file Then Return 
				theInt = file.ReadInt()
				Print "First int in file is :" + theInt
				file.Close	
			Endif
			
			If KeyHit(KEY_S)
				Print "attempting to save to file"
				Local file:=FileStream.Open(configFilePath,"w")
				If Not file Then Return 
				file.Seek(0)
				file.WriteInt theInt
				file.Close	
			Endif
	End
	
	Method OnRender()
	      Cls
	      DrawText "Left arrow to decreases theInt, Right arrow to increase",0,12
	      DrawText "L To load theInt's value, S to save it",0,24
		  DrawText "theInt = "+ theInt,0,36
	End

End		

Function Main()

	New MyApp
	
End


Any pitfalls to this method?

Someone on stackoverflow warned that the HOME var was no available to OS X gui apps, only to apps launched via the console, but this does not seem the case with monkey-made apps.

APPDATA is supposed to be valid for Win XP, Vista and 7 (don't know about 8). HOME should be valid for all OS X versions, afaik...


marksibly(Posted 2013) [#2]
Looks good to me.

Glfw apps on MacOS X are really console apps I believe, so that's why HOME env var works.

You can also use FileType( path ) to check if a dir exists.


Raph(Posted 2013) [#3]
Should SaveState()/LoadState do this automatically on those platforms?

XNA for Windows seems like it could work the same way. Does Win8 on PC have rules for its data files?


John McCubbin(Posted 2013) [#4]
Great stuff, saves to "C:\Users\*USERNAME*\AppData\Roaming\"

Tested on Windows 8


SLotman(Posted 2013) [#5]
This is wrong for Mac OS-X and sanboxed apps.

Data needs to be saved on "~/Library/Containers/<bundle_id>/Data/Library/Application Support/<app_name>/"

(*very ugly*, I know, but its what Apple's docs say about it)

With the code above, as soon as you check "sandbox mode" into XCode, the app will crash.

Edit: Nevermind, GetEnv("HOME") return the correct path... but my game is still crashing, I don't know why :(