About Monkey 2 › Forums › Monkey 2 Programming Help › stream, binary file
This topic contains 12 replies, has 4 voices, and was last updated by 
 medi
 2 years ago.
- 
		AuthorPosts
 - 
		
			
				
March 17, 2017 at 2:27 pm #7531
I need help on this, I want to write this c code in mx2:
Monkey123456FILE *fptr;fptr = fopen("scores.dat", "rb+");if(fptr == NULL) //if file does not exist, create it{fptr = fopen("scores.dat", "wb");}I wrote this which I am extremely doubtful about and is not working:
Monkey1234567891011121314151617181920212223242526272829303132333435Namespace alltests#Import "<std>"Using std..Function Main()Test("This is a test:")EndFunction Test(write_my_string:String)Print write_my_stringPrint "--"' write to binary fileLocal file_stream:Stream = Stream.Open( "data", "rw" )If not file_streamPrint "Oh, no!"ReturnEnd If'read from binary filefile_stream.WriteString(write_my_string + " 78")Local read_my_string:String = file_stream.ReadString()Print read_my_stringfile_stream.Close()End FunctionThe program compiles but seems not working because “data” is not created and is not read.
After the text file version of it didn’t work either, I used LoadString, which worked. I like both binary and text version works to learn mx2.
March 17, 2017 at 11:06 pm #7534use FileStream to write to a file (FileStream extends Stream)
[/crayon]Monkey123[crayon-5cba152b663dd161818720 inline="true" ]Local stream:=FileStream.Open(path,"rw")March 18, 2017 at 2:02 am #7537Monkey 2’s file streaming capabilities have some “quirks” depending on the target platform. (eg The “rw” mode is not working for me on MacOS). You’re also limited to the file types you can “#Import”.
You can, however, create, load and save files at runtime. The location of the created files will depend on the target platform and the chosen target directory.
Here’s an example that creates, saves and loads one text and one binary file to your desktop (tested on MacOS, might encounter file permission issues on other platforms?)
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177[crayon-5cba152b69346871984872 inline="true" ]#Import "<std>"Using std..Function Main()Local urlText := DesktopDir() + "test.csv"Local urlBinary := DesktopDir() + "test.dat"Local scores := New Scores()'****Check if our text-based csv file already exists.Local file := FileStream.Open(urlText, "r")If Not file 'If not then create it using some test data.scores.ParseCSV("Bob, 200~nAnna, 220~nMick, 18~nAi, 333")scores.SaveCSV(urlText)Elsefile.Close()Endif'****'****Check if our binary data file already exists.file = FileStream.Open(urlBinary, "r")If Not file 'If not then create it using some test data.scores.ParseCSV("Don, 0~nPeta, 499~nStu, 88~nCarl, 600")scores.SaveBinary(urlBinary)Elsefile.Close()Endif'****'Load Both files into our scores manager and print them all.scores.LoadCSV(urlText)scores.LoadBinary(urlBinary, True)scores.PrintAll()End'--------------Class ScoresPrivateField _scores:Stack<Score>PublicMethod New()_scores = New Stack<Score>EndMethod LoadCSV:Void(url:String)If Not url Then ReturnParseCSV(LoadString(url))EndMethod SaveCSV:Void(url:String)If Not url Then ReturnIf Not _scores Then ReturnLocal str:StringFor Local score := eachin _scoresstr += score.ToCSVString()EndIf Not SaveString(str, url)Print "Could not save csv file: " + urlEndifEndMethod ParseCSV:Void(csvDB:String, append:Bool = False)If Not csvDB Or csvDB.Length <= 0Print "Invalid CSV data."ReturnEndifLocal csvRecords := csvDB.Split("~n")If Not _scores Then _scores = New Stack<Score>()If Not append Then _scores.Clear()For Local i := 0 Until csvRecords.LengthLocal csvRecordFields := csvRecords[i].Split(",")If csvRecordFields.Length < 2 Then Continue 'Invalid record so skip it._scores.Push(New Score(csvRecordFields[0].Trim(), Cast<UInt>(csvRecordFields[1])))NextEndMethod LoadBinary:Void(url:String, append:Bool = False)If Not url Then ReturnLocal file := FileStream.Open(url, "r")If Not filePrint "Could not read binary file: " + urlReturnEndifIf Not _scores Then _scores = New Stack<Score>()If Not append Then _scores.Clear()Local numRecords := file.ReadInt()Local recordCounter := 0While (Not file.Eof) And (recordCounter < numRecords)_scores.Push(New Score(Cast<String>(file.ReadCString()), file.ReadUInt()))recordCounter += 1Wendfile.Close()EndMethod SaveBinary:Void(url:String)If Not url Then ReturnIf Not _scores Then ReturnLocal file := FileStream.Open(url, "w")If Not filePrint "Could not write binary file: " + urlReturnEndiffile.WriteInt(_scores.Length)For Local score := Eachin _scoresfile.WriteCString(score.Name)file.WriteUInt(score.Value)Nextfile.Close()EndMethod PrintAll:Void()For Local score:= Eachin _scoresPrint score.ToString()NextEndEnd' ----------Struct ScorePublicField Name:StringField Value:UIntMethod New(name:String, value:UInt)Name = nameValue = valueEndMethod ToString:String()Return Name + "~t~t" + ValueEndMethod ToCSVString:String()Return Name + ", " + Value + "~n"EndEndMarch 18, 2017 at 2:36 am #7538To impixi, it works perfect in my Windows 8 machine. Thanks a bunch! I will study your code to correct mine.
March 18, 2017 at 4:21 am #7539I said perfectly? May be not, but not your fault. It gives me strange behavior for different read and write locations. HOWEVER, I am using the binary version of mx2, which is very old. I will compile the latest version tomorrow to test my codes again.
for write:
Monkey123456789101112131415161718192021222324#Import "<std>"#import "assets/"Using std..Function Main()Local url:= AssetsDir() + "file.dat"Local file:=FileStream.Open(url, "w")If Not filePrint "Something wrong"returnEnd IfLocal write_this:String = "String 1, String 2"file.WriteString(write_this)file.Close()Endfor read:
Monkey123456789101112131415161718192021222324#Import "<std>"#import "assets/"Using std..Function Main()Local url:= AssetsDir() + "file.dat"Local file:=FileStream.Open(url, "r")If Not filePrint "Something wrong"returnEnd IfLocal read_it:Stringread_it = file.ReadString()file.Close()EndNevertheless, it seems I am progressing.
March 19, 2017 at 4:47 pm #7546Yes impixi, for the text file version, I get memoey access error when I use anything other than DesktopDir(). Unlike the above simplified binary examples, using AssetsDir() fails. There is a CurrectDir() as well, same problem. Don’t know what is going on. Do I doubt myself or Monekey2
No project can begin without io system. Buying and using veterans’ libraries or frameworks, no way. Fundamentals must work and clearly documented first. Double thanks to you impixi
Monkey12345678910111213141516171819202122import "<std>"#Import "assets/"Using std..Function Main()local url:= DesktopDir() + "textfile.txt"local text_file:= FileStream.Open(url ,"r")If Not text_filePrint "no file, creating: "SaveString("test", url, true)End Iftext_file.Close()Print "Done"EndMarch 19, 2017 at 7:24 pm #7548using absolute path returned by
[/crayon]Monkey123[crayon-5cba152b7a38c595605931 inline="true" ]filename = RequestFile("Save the file","",True)I could save where I want on W7 except my sys root dir (C:\ –> no error but no files)
on OSX I can only save on user dir if on sys drive (memory acces violation if not user dir), everywhere on other drives
the filter is not working on OSX so
[/crayon]Monkey123[crayon-5cba152b7a393972900005 inline="true" ]filename = RequestFile("Save the file","png",True)will crash too
never used assetsdir(), desktopdir(),…
all this should be reported on github when we have a clearer idea of where it actually crashes/not-working.
March 19, 2017 at 8:18 pm #7549Thanks abakobo, I keep in mind.
March 20, 2017 at 1:06 am #7550I think we need to expose a few additional folders so we can do our file handling in a more “appropriate” manner, ie according to modern expectations.
Here’s a good link for iOS / MacOS X:
I don’t have time right now, but later I’ll have a crack at exposing the Documents and Library folders via a wrapper or maybe a modification to std.filesystem (if nobody else does it first).
I haven’t looked into the other target platforms yet, but the principles are the same IIRC. In any case I need the functionality for Mac OS X and Windows 10, so minimally that’s what I need to get working at some point…
IIRC Brucey had a “bah.volumes” BlitzMax module that exposed appropriate folders/directories on the various platforms – I wonder if any of that c/c++ native code would be useful for us…
March 20, 2017 at 1:46 am #7551Actually, it would be nice if I could do this on MacOS X to access/read/write to the user’s Documents directory:
[/crayon]Monkey12345678910111213141516171819[crayon-5cba152b81202070535366 inline="true" ]#Import "<std>"Using std..Function Main()Local url:="~~/Documents"Print urlChangeDir(url)Local docs := LoadDir(".")For Local doc := Eachin docsPrint docNextEndBut, alas, it’s not that simple.
March 20, 2017 at 2:02 am #7552Well, that was simpler than I thought. Works on MacOSX, untested on Windows. It pays to poke around monkey2’s source code (I merely copied and modified the DesktopDir function).
[/crayon]Monkey1234567891011121314151617181920[crayon-5cba152b83fa6626122581 inline="true" ]#Import "<std>"#Import "<libc>"Using std..Using libc..Function Main()Print DocumentsDir()EndFunction DocumentsDir:String()#If __TARGET__="windows"Return (String.FromCString( getenv( "HOMEDRIVE" ) )+String.FromCString( getenv( "HOMEPATH" ) )).Replace( "\","/" )+"/Documents/"#Else If __DESKTOP_TARGET__Return String.FromCString( getenv( "HOME" ) )+"/Documents/"#EndifReturn ""EndEDIT: And it works in place of the DesktopDir() function in my earlier file creation/reading/writing test code. Just remember to import libc..
March 20, 2017 at 10:29 pm #7561Hi,
AssetsDir() is working OK here (see below) although you can’t depend on it being present on all targets (eg: there is no AssetsDir on android).
I’m happy to add more of these BlahDir()s though if people let me know what they want.
Monkey1234567891011121314#Import "<std>"Using std..Function Main()Print "AssetsDir="+AssetsDir()SaveString( "Hello World!",AssetsDir()+"test.txt" )Print LoadString( AssetsDir()+"test.txt" )EndMarch 23, 2017 at 2:20 pm #7579Thanks for all your help. This was for my Premier League software. Since PL will end soon, I got to finish it very soon. As my learning Monkey2 is slow, I will go back to Java or BlitzMax. I will convert my codes to Monkey2 in summer (for the next season of PL).
 - 
		AuthorPosts
 
You must be logged in to reply to this topic.