Saving Data To File

Blitz3D Forums/Blitz3D Programming/Saving Data To File

Whats My Face(Posted 2009) [#1]
What I'm trying to do is when a player logs out of a game (online) the server, right before it deletes the player, opens up a file that contains the player's information and saves all the new data. The way the file system works is that the file name is the user name for the player and the first line is the password. After that comes the player x, y, and z coordinates (each with its own line) and I'm not trying to do anything past there for now. The problem is that when the player logs out the first time everything works great but every time after that the new data doesn't overwrite the old data. The code that I'm currently using is:

;this writes the player data into the players file before it logs the player off
Local curUserFile = OpenFile(u\file$)
			
;get to the correct position in the file
ReadLine$(curUserFile)
WriteLine curUserFile,""
			
WriteLine curUserFile,u\x#
WriteLine curUserFile,u\y#
WriteLine curUserFile,u\z#
CloseFile curUserFile


So what I'm doing is opening the file reading a line (the line for the password) just to get it out of the way then writing a blank line so I can move on to the next line then writing all the player data and exiting the file.

How can I make it so that the x, y, and z coordinates are rewritten every time. By the way, another thing I noticed is that when I make sure the player file only has one line (the line with the password on it) the program works fine but when I press enter and make another empty line the program doesn't work.


GIB3D(Posted 2009) [#2]
Use WriteFile instead of, or after, OpenFile. You can Open it, read whatever you may need, close it, then use Write on it.


Warner(Posted 2009) [#3]
How about using SeekFile?


GIB3D(Posted 2009) [#4]
I've never figured out how to use SeekFile properly so I can't help you with that. But I already made a thing to save a UserConfig file. It's pretty much the same thing you have except I have one function for reading it and the other for writing it.


Gabriel(Posted 2009) [#5]
Trying to overwrite an existing file becomes tricky when strings are involved. Strings are of variable length, and I'm not sure what will happen if you overwrite the end of an existing file you've opened for reading and writing. The docs aren't particularly helpful in this regard either, simply warning

Note extreme care needs to be exercised when updating files that contain strings since these are not fixed in length.


It might be safer to do what GIA_Green_Fire_ suggests and read the file to get the password, close it, then overwrite the file completely with WriteFile.


Warner(Posted 2009) [#6]
The problem is that the Strings vary in length. Strings, written with WriteLine, end with Chr$(0). If you overwrite a string with a shorter string, you'll end up with two strings:
HELLO WORLD*  --> original string with Chr$(0), rep. by "*"
BYE*O WORLD*  --> string is overwritten with new string, now there are 2 strings

Maybe you could look into ReadString/WriteString? I believe that ReadString allows to specify the number of characters the string contains.
Eitherway, if every string has a fixed length, you can update them more easily. I believe you can do that with the RSet/LSet functions.


Yasha(Posted 2009) [#7]
Strings, written with WriteLine, end with Chr$(0).


Incorrect. Strings written with WriteLine end with Chr(13)+Chr(10).

Strings written with WriteString have no specific terminator, but instead are preceded with a four-byte int containing the number of characters in said string.


Warner(Posted 2009) [#8]
Ah, yes, I was confusing it with the null-terminated string used in Windows api's. My bad, but the idea is the same, except with a 2 byte terminator, the chance of messing up the file data is bigger. Using a fixed-length string might make stuff easier still.


Bobysait(Posted 2009) [#9]
I believe you can do that with the RSet/LSet functions.

I think it's the best way, if you don't want to overwrite all the file.
You need a "max fixed string Length".
Then you always write the line with this Size.

F=Openfile(your file)
l$=Writeline(f, RSet(StringToSave,32)) ; here it stores 32 chars string.

when you read the file:
F=ReadFile(Your File)
SavedName$=Trim(ReadLine(F))

to overwrite a file without disturbing the structure, you need to fit every fields with the exact same size each time you write in. Else, you'll destroy the feed line etc... and offset will be changed.


But the real best way would be to use SeekFile with constant offsets.

for eg, we 'll use a 32 chars length for name
16 chars for pass and 15 for Ip ( XXX.XXX.XXX.XXX )
Const SAVE_Offset_NAME%=0
Const SAVE_Offset_PASW%=36 ; 32+4
; 32 is the size of name and 4 is the size of an int (used to store the string length )
Const SAVE_Offset_IP%=56 ; [32+4]+16+4
; it is the name offset + the pass word offset
Const SAVE_Offset_...%=75 ; [32+4 +16+4]+ 15+4
; etc...

F=OpenFile(MyFile)
writestring(f,RSet(Name, 32))
WriteString(f,RSet(PasW, 16))
WriteString(f,RSet(182.265.32.7, 15))
etc...

then to read the file go to the offsets
eg, i wnat to just get the password :
F=readFile(MyFile)
SeekFile(SAVE_Offset_PASW)
Pass$=trim(ReadString(F))

and if you want to just overwrite a field like the Ip ( that may change every time you reboot ) :
f=OpenFile(MyFile)
SeekFile(SAVE_Offset_IP)
WriteString( RSet(12.123.234.456 , 15) )

if will overwrite without changing anything else in the file structure.


Bobysait(Posted 2009) [#10]
Here is an simple exemple involving a super gameplay :)



Sorry for my pour ugly english ^^


WERDNA(Posted 2009) [#11]
Hey thanks a lot Bobysait!

I was just wondering how to work with saving strings for my robo attack
high scores screen :)


Thanks!

WERDNA


Bobysait(Posted 2009) [#12]
You're welcome ;)