File io help

#1
I want to save load scores, load maps ect but after looking at docs still have no idea. I managed to get app to start but no saved text.

Can someone provide a save load example for me. Greatly appreciated thx
 

MikeHart

Administrator
Staff member
Administrator
#2
Which platform? Can you post what you have so far regarding the file loading?

Did you look at the 2 file scripts in the mojo/mak folder?
 
#3
this is what i got, just trying to figure this out, and im not sure what youre talking about folders or scripts mike

Code:
Strict

Import mojo
Import brl.filestream

Class gamename Extends App
Field file:FileStream
        Method OnCreate:int()
            SetUpdateRate(60)
           
            file = New FileStream()
           
            Return 0
        End
       
       
        Method OnUpdate:int()
         file = FileStream.Open("file.txt","u")
            file.WriteString("String")
            file.Close
           
            Return 0
        End
       
       
        Method OnRender:int()
            Cls 0,0,0
           
            Return 0
        End
End


Function Main:int()

    New gamename()
   
    Return 0
   
End
 

dawlane

Active Member
CX Code Contributor
#6
Can someone provide a save load example for me. Greatly appreciated thx
Files will be output at application executable level as in the second image the Mike posted. See the Resource paths in the documentation for other locations.

EDIT: When you write data to a file you will have to consider how that data is to be represented within that file to be able to successfully read it back.

EDIT": You should also consider using Try, Catch blocks to trap any errors while reading and writing to a file.
 
Last edited:

dawlane

Active Member
CX Code Contributor
#7
As it's Christmas here's an example for a high score table.
Code:
Strict

' Import the file stream and the filesystem modules
Import mojo    ' Needed for getdate
Import brl.filestream
Import brl.filesystem

#Rem
    As building refreshes the data directory the path will be set to empty so that the hi score file will be at the same level as the executable
    Edit the DATAPATH constant to use the cerberus://data/ directory.
#End
Const DATAPATH:="" '"cerberus://data/"
Const ENTRIES:=20    ' Total number of high score entries. NOTE that you have to delete the old high score save file if you change this.

' Simple class data structure to hold a high score with the players name
Class CHighScore
    Field name:String
    Field score:Int
 
    Method New( n:String, s:Int )
        name=n
        score=s
    End Method
End Class

' The High Score Table class will create a new high score table or load a previous high score table
Class CHighScoreTable

    Field highScores:=New Stack<CHighScore>    ' Holds the entries for the high scores
 
    ' Either load a previously saved high score table or create a new one
    Method New()
        If FileType( DATAPATH+"hiscore.txt" )=FILETYPE_FILE
            Print "Found High Score File"
            ReadTableIn()
        Else
            Print "Creatings New High Score Table"
            For Local i:=1 To ENTRIES
                Self.highScores.Push( New CHighScore( "Player "+i, i*100 ) )
            Next
        
            ' The new high score file should be written here, but for this example it's going to be written else where.
            'Self.WriteTableOut()
        Endif
    End Method
 
    ' Displays the high score table in reverse order. The last one pushed needs to be the highest score.
    Method ShowHighScores:Void()
        Local rank:=0
        For Local i:= Eachin Self.highScores.Backwards()
            rank+=1
            Print "RANK "+rank+" "+i.name+" "+i.score
        Next
    End Method
 
    #Rem
        Use this to check to see if the player has attained a high score.
        If the player has attained a high score; then it will return the rank position index, eles it will return -1.
    #End
    Method IsHighScore:Int( s:Int )
        ' The index needs to start at the last item pushed onto the stack
        Local idx:=Self.highScores.Length()-1, hiScorer:CHighScore
        While idx >-1
            hiScorer=Self.highScores.Get( idx )
            If hiScorer.score<=s Exit
            idx-=1
        Wend

        Return idx
    End Method
 
    ' Update the high score table and write the results back to the high score table file.
    Method UpdateHighTable:Void( n:String, s:Int, idx:Int )
    
        ' Remove the bottom item from the stack before inserting the new high score.
        Self.highScores.Remove( 0 )
        Self.highScores.Insert( idx, New CHighScore( n, s ) )
    
        ' The updated high score file should be written here, but for this example it's going to be written else where.
        'Self.WriteTableOut()
    
    End Method
 
    ' Write the high score table to a file.
    Method WriteTableOut:Void()
        Local f:FileStream
    
        #Rem
            WriteShort, WriteString and WriteInt are high level stream operations.
            The stream position is automatically updated and any write errErrorn be caught within
            a Try/Catch block.
        #End
        Try
    
            f=FileStream.Open( DATAPATH+"hiscore.txt", "w" )    ' Open the high score file in write mode only.
            For Local i:=Eachin Self.highScores
                ' Variable name lengths
                f.WriteShort( i.name.Length() )     ' High score name length
                f.WriteString( i.name )                ' High score name is of variable length
                f.WriteInt( i.score )                 ' High score stored as a integer
            Next
            f.Close()
            Print "High score file successfully written."
        
        ' Report an error giving the position in the stream of where the write failed.
        Catch err:StreamWriteError
            Local p:=f.Position()
            If f<>Null f.Close()
            Error  "High Score Table write error! Position is "+p
        End
    End Method
 
    ' Read the high score table to a file.
    Method ReadTableIn:Void()
        Local f:FileStream
    
        #Rem
            ReadShort, ReadString and ReadInt are high level stream operations.
            The stream position is automatically updated and any write error can be caught within
            a Try/Catch block.
        #End
        Try
            f=FileStream.Open( DATAPATH+"hiscore.txt", "r" )
            Local len:=0, n:="", s:=0
        
            ' Read the data in until the End Of File has been reached.
            While Not f.Eof
                len=f.ReadShort()        ' Get the length of the name string to read
                n=f.ReadString( len )    ' Read the name string
                s=f.ReadInt()            ' Read the score
                Self.highScores.Push( New CHighScore( n, s ) )
            Wend
            f.Close()
            Print "High score file successfully read."
        
        ' Report an error giving the position in the stream of where the read failed.
        Catch err:StreamReadError
            Local p:=f.Position()
            If f<>Null f.Close()
            Error  "High Score Table read error! Position is "+p
        End
    End Method
End Class

' The first run will show the default table entries, subsequent runs should add a new player with a new high score to the table.
Function Main:Int()
    Local date := GetDate()
    Seed = date[3] * 3600000 + date[4] * 60000 + date[5] * 1000 + date[6]
 
    Local highScoreTable:= New CHighScoreTable()    ' Create a high score table
 
    ' Only add to the high scores if the high score file exists.
    ' Each re-run should give a different player with a different high score if the score is high enough.
    If FileType( DATAPATH+"hiscore.txt" )=FILETYPE_FILE
        Local names:String[]=[ "MikeHart","dawlane","Holzchopf","Martin","muruba","Phil7","Gerry Quinn","Dubbsta","PixelPaladin","Ferret3D" ]
        Local player:=names[ Rnd(names.Length()-1) ], score:=Int( Rnd(6000) ), idx:=highScoreTable.IsHighScore( score )
        Print "Generating new player high...."
        Print "Player: "+player+" with a score of: "+score
        If idx>-1 highScoreTable.UpdateHighTable(  player, score, idx )
    Endif
 
    ' Write the high score table to file before displaying it.
    highScoreTable.WriteTableOut()
    highScoreTable.ShowHighScores()
    Return 0
End Function
If you opened the highscore.txt file, you will see that it displays garbage. But you will be able to make out the names.
 
Last edited:
#8
:D awe shucks, ty Dawlane! I really didnt think it would be so much involed, cant wait to analyze. yeah found it in the folder Mike thanks
 
#9
The problem with file IO is that it is platform dependent. If you can get away with it, there are SaveState and LoadState functions that save/load a single string on all platforms, which are fine for hi-score etc.

Your maps will have to be loaded a different way though (but all platforms can load stuff even if they are not great for saving).

And if you want users to be able so share files, you have no choice but to confront the full file system across platforms.
 

dawlane

Active Member
CX Code Contributor
#11
SaveState is best used to store small amounts of data such as application preferences or hi-score tables. And if I remember there is a size limit to LoadString/SaveString depending on the target.

If you want to load level maps, you should decide on how you are going to load that data for use. There are a number of applications that you can use to build levels, you just have to write code to deal with the data. The most popular export formats for these applications are either xml or json. Cerberus supports the latter to a certain degree and there is a xml module by skn3 if I recall somewhere post around here or on github.
 
Last edited:

Phil7

Active Member
#12
LoadString(path:String) is quite easy to use for loading maps and multiplatform. The only thing I remember, giving me a headache, was that the textfiles have to be utf-8. I used notepad++ for checking and converting.
 
Top Bottom