How to output to a file?
Monkey Forums/Monkey Programming/How to output to a file?
| ||
Is there a way to output data to a file? I tried SaveString function but it didn't work. I noticed that it is on a different module called os but it looks like it doesn't support most targets as it only has cpp in the native folder. What is the difference between LoadString function that's in the mojo module and the one in the os module? Is there a module that add support to this functionality? I think this is a very important and handy feature and would be surprised if monkey still lacks it at this point. |
| ||
The native LoadString doesn't actually get the string from a file, the string is actually embedded in the source code. What target do you want to work on? It isn't possible for Html5 or Flash to create a file. Also, have you looked at the SaveState() command? |
| ||
Monkey is meant to be a multiplatform programming language. Since you aren't going to be able to save files in Flash and HTML, you shouldn't expect this functionality. The OS module was likely intended for people who wanted to make tools, not for the game's themselves. os.LoadString = Loads a file from anywhere in the system, and the binary executable is the starting path mojo.LoadString = Loads a file from the data folder if on certain platforms, otherwise the files are embedded and loaded internally. SaveState = Will save to the only available file that can be altered LoadState = Will load from the only available file that can be altered The closest thing to multiple file manipulation that you'll get is one of the virtual file systems. Although, that's probably not what you're looking for. Goodlookinguy: Simple File System GfK: File System |
| ||
I think writing it off because of multiple targets is unfortunate. Couldn't Flash and HTML5 save to cookies as if they were files to get around this? Then have file-system access on iOS/Android/GLFW. I'm not familiar with XNA for win phone or xbox, but I assume there is some alternative if not file access as well. File system access is possible on mobile apps, so it should be in Monkey if even just for mobile targets. You can easily specify valid targets in modules and your code. |
| ||
Erm, something I knocked up for my own use when testing, bit basic but it does me as I want to save stuff other then in the data folder:- {approot}/nativefilesystem/nativefilesystem.monkey #if TARGET="glfw" Import "native/nativefilesystem.${TARGET}.${LANG}" #EndIf Extern #If TARGET="glfw" Then Function WriteFile:int(path:string) = "NativeFileSystem::WriteFile" Function WriteLine:void(line:string) = "NativeFileSystem::WriteLine" Function ReadFile:int(path:string) = "NativeFileSystem::ReadFile" Function ReadLine:string() = "NativeFileSystem::ReadLine" Function CloseFile:void() = "NativeFileSystem::CloseFile" #Else Public Function WriteFile:int(path:string) Return 0 end Function WriteLine:void(line:string) End Function ReadFile:int(path:string) Return 0 End Function ReadLine:string() Return "" End Function CloseFile:void() end #EndIf {approot}/native/nativefilesystem.glfw.cpp #include <stdio.h> typedef wchar_t OS_CHAR; static char *C_STR( const String &t ){ return t.ToCString<char>(); } static OS_CHAR *OS_STR( const String &t ){ return t.ToCString<OS_CHAR>(); } FILE *pFile; class NativeFileSystem { public: static int WriteFile(String path) { pFile = _wfopen(OS_STR(path),L"w"); if(pFile!=NULL) { return 1; } return 0; } static int ReadFile(String path) { pFile = _wfopen(OS_STR(path),L"r"); if(pFile!=NULL) { return 1; } return 0; } static String ReadLine() { wchar_t newString[256]; fgetws(newString,256,pFile); String line = String(newString); return line; } static void WriteLine(String line) { String newLine = line+"\n"; fputws(OS_STR(newLine),pFile); } static void CloseFile() { fclose(pFile); } }; Example:- Method SaveStats:Void() Local timeFinished:Int = levelTimer Local bestTime:Int Local statString:String local result:Int = ReadFile("data\store\"+(currentLevel)+"stat.txt") bestTime = int(ReadLine()) CloseFile() if timeFinished > bestTime statString = timeFinished Local pathString:String if IDE_TEST = True pathString = "..\..\..\..\Match3.data\store\"+(currentLevel)+"stat.txt" Else pathString = "data\store\"+(currentLevel)+"stat.txt" EndIf WriteFile(pathString) WriteLine(statString) CloseFile() EndIf End Obviously no use what's so ever other then GLFW (In Windows), but, if your looking at file system stuff on other targets, your in for some pain! Dabz |
| ||
I use SaveState and LoadState all the time for my settings and believe me, I have lots of them. I needed something so that I can write log file. benmc, SaveState and LoadState in html5 and flash are actually using cookies. reading and writing to files doesn't make sense that much in those targets. But that doesn't mean it is not necessary for other targets. Thanks Dabz. I just managed to do something similar but for android. Here is my code(Modified so it can be easily added to diddy): in diddy/native/diddy.android.java: import android.content.Context; // necessary but already there in diddy.android.java // add this line to the top of the file: import java.io.FileOutputStream; class diddy { //add the following 2 methods to the top of the diddy class: static void saveStringToFile(String message, String filename) { FileOutputStream fos; try { fos = MonkeyGame.view.getContext().openFileOutput(filename, Context.MODE_PRIVATE); fos.write(message.getBytes()); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } } static String loadStringFromFile(String filename) { FileInputStream fis; try { fis = MonkeyGame.view.getContext().openFileInput(filename); fis.read(); ByteArrayOutputStream content = new ByteArrayOutputStream(); int readBytes = 0; byte[] sBuffer = new byte[512]; while ((readBytes = fis.read(sBuffer)) != -1) { content.write(sBuffer, 0, readBytes); } String message = new String(content.toByteArray()); fis.close(); return message; } catch (FileNotFoundException e) { e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } return ""; } } in diddy/functions.monkey: #If LANG="java" Then Function SaveStringToFile:Void(message:String, filename:String) = "myGUI.saveStringToFile" Function LoadStringFromFile:String(filename:String) = "myGUI.loadStringFromFile" #Else Function SaveStringToFile:Void(message:String, filename:String) End Function LoadStringFromFile:String(filename:String) return "Target Not Supported" End #End This will Open a private file associated with this Context's application package for writing "SaveStringToFile" or reading "LoadStringFromFile". SaveStringToFile Creates the file if it doesn't already exist. File will not be viewable or accessible unless you change MODE_PRIVATE to: MODE_APPEND to append to an existing file MODE_WORLD_READABLE to control reading permissions. MODE_WORLD_WRITEABLE to control writing permissions. and here is how to use it: str:String =LoadStringFromFile("log.txt") SaveStringToFile(str,"log.txt") Now we need someone to write the code for XNA and ask therevills to add it to diddy :P |
| ||
and That is the native code for XNA:public static void saveStringToFile(string message, string filename) { #if WINDOWS FileStream stream = File.Open(filename, FileMode.OpenOrCreate); #else IsolatedStorageFileStream stream = new IsolatedStorageFileStream( filename, FileMode.OpenOrCreate, IsolatedStorageFile.GetUserStoreForApplication()); #endif using(StreamWriter writer = new StreamWriter(stream)) { writer.Write(message); } } public static string loadStringFromFile(string filename) { string message; #if WINDOWS FileStream stream = File.Open(filename, FileMode.OpenOrCreate); #else IsolatedStorageFileStream stream = new IsolatedStorageFileStream( filename, FileMode.OpenOrCreate, IsolatedStorageFile.GetUserStoreForApplication()); #endif using (StreamReader reader = new StreamReader(stream)) { message = reader.ReadToEnd().ToString(); } return message; } This will open or create a file in the same directory the app is running from. this has to be in a .cs file inside a class(just type "class something{" at the top and close it at the end. Can be used just like the android one on top of this post. #Edit: Had to change the code a little bit so that it works with windows as well as windows phone and xbox360 |