Prob opening file calling sub function to write, then write from parent function
BlitzMax Forums/BlitzMax Programming/Prob opening file calling sub function to write, then write from parent function
| ||
| I've been trying to build a function for saving information from types to files. The problem I ran into is that if I try to write after the function runs, it just comes up as a zero when I read the file. I have tried passing the file name to the function, opening it there, and then reopening to write to it. But for some reason that writes all zeros. Is what I'm trying to do possible? Thanks for reading. |
| ||
| First: start using 'Superstrict' at the top of all your programs. Second: It might be easier to build a string for your data and just call the function SaveText() third: Look at the doc under 'streams' to see some simple examples of reading and writing to files. |
| ||
| I'm trying to make a function to put in the middle of a "For EachIn" loop, so I don't have to use the same block of code for each variable in the type. Using strings would be more complicated, as I would have to convert them back on reload. And strings don't have a set sizes on the file. |
| ||
I completed your code with the rules of SUPERSTRICT and it runs perfect.SuperStrict
Global t%[]
Global ex:TStream
Global ast% =0
ex = WriteStream ("OOP.dat")
t = [4,8,5]
ast=SaveData (ex,ast,t)
ast:+4
SeekStream (ex,ast)
WriteInt (ex,8)
CloseStream (ex)
ex =ReadStream ("OOP.dat")
ast=0
For Local g%=1 To 5
SeekStream (ex,ast)
Print "POS" + g% + "=" + ReadInt (ex)
ast:+4
Next
CloseStream (ex)
Function SaveData% (in:TStream Var,pos%,a%[])
Local b%, i%
For b=EachIn a.Dimensions()
Next
For i=0 To b-1
SeekStream (in,pos)
WriteInt (in,a [i])
pos:+4
Next
Return pos
End Function
Your only mistake is, that you add 4 to the file pointer before writing the last variable "8". So now your "8" is on position 5. Run my sample to see what I mean. |
| ||
| FYI, Using the stream read/write functions automatically advance the file position pointer, so there's no need to use SeekStream in your scenario, unless you intend to use it for some kind of padding? Your code will perform better seeking once ( to a required position ) before your read/write code - assuming you need to seek at all? |
| ||
| I would save Type data to a file and read it back as follows; WARNING - not tested.
Strict
Graphics(640,480)
'// Store our band members in a list
Global TheBand:TList = New Tlist
'// Add some band members
AddBandMemeber("John",45,"Guitar")
AddBandMemeber("Dave",38,"Drums")
AddBandMemeber("James",41,"Keyboard")
'// Main Loop
Repeat
cls
if keyhit(KEY_S) SaveBand()
if keyhit(KEY_L) LoadBand()
if keyhit(KEY_ESCAPE) End
flip
Forever
'// Band member object
Type TBandMember
Field name:string
Field age:Int
Field instrument:String
Method ExportToStr:String()
Return(name+","+age+","+instrument)
End Method
End Type
'// Create a band member (object) and add to the band (list)
Function AddBandMemeber:Int(_name:String,_age:Int,_instrument:String)
local a:TBandMember = new TBandMember
a.name = _name
a.age = _age
a.instrument = _instrument
TheBand.AddLast(a)
End Function
'// Save all band members as a Delimiter-separated string to a file
Function SaveBand:Int()
local seperator:String = "|"
local band_data:String
'// Build the string to save
For local a:String = eachin TBandMember.Value()
band_data = band_data + a.ExportToStr() + seperator
Next
'// Save the string file
local fileOut:TStream = WriteStream("blah\blah\file.txt")
writestring(fileOut, band_data)
Closestream(fileOut)
End Function
'// Load the Delimiter-separated string from a file, then split the string to re-created each band member
Function LoadBand:Int()
local seperator1:String = "|"
local seperator2:String = ","
local band_data:String
'// Read the file
local fileIn:TStream = ReadStream("blah\blah\file.txt")
If Not fileIn Then Notify "Cannot find file" ; End
band_data = ReadString(fileIn)
closeStream(fileIn)
'// Print results
Print band_data
'// Create each band member
local member:String[] = band_data.split(seperator1)
For local a:Int = 0 until member.length-1
local thisBandMember:String[] = member[a].split(seperator2)
AddBandMemeber(thisBandMember[0],Int thisBandMember[1],,thisBandMember[2])
Next
End Function
|
| ||
| @ coffeedotbean Let's hope none of your bandmembers uses an artst name like "The big, big Mr. M". Using delimiters with strings _always_ enforces proper enquoting of the delimiter - and therefor of the the enquoting-string too so here: The big, big Mr. M becomes eg. The big\, big Mr. M To be able to use "\" and "," you need to enquote "\" too, so "\" becomes "\\". How to achieve that? Look how BlitzMax modules handles "~" enquoting. @ saving types Did you consider using Brucey's persistence.mod - it allows to serialize data to XML (and to json). bye Ron |
| ||
| @Derron - ah yes always pick your Delimiter(s) wisely :p, doesn't have to be single char either. |
| ||
| Hi, you can also use reflection to get type data like: SuperStrict Local me:Person = New Person Print GetObject( me ) Type Person Field name:String = "Henri" Field age:Int = 20 Field instrument:String = "Guitar" EndType Function GetObject:String(obj:Object) If Not obj Then Return Null Local Tid:TTypeId = TTypeId.ForObject(obj) Local Fields:TField[] = TField[](Tid.Fields().ToArray()) Local line:String For Local i:Int = 0 Until Fields.length If i > 0 Then line:+ " ; " line:+ Fields[i].Name() + " = " + String(Fields[i].Get(obj) ) Next Return line EndFunction -Henri |
| ||
| @Midimaster That fixed it. Leave it to me to do something like that. lol @col It feels like I used to know that, and then forgot. Probably because most of my read functions check for a non zero at the start of the file, and one early function jumps around in the file a lot. So I probably just got used to using SeekStream by the time I started making save functions. @coffeedotbean That look like a good way to save strings or mixed data. I'll have to remember you and GW's suggestion about that. Thanks for all of your help guys! |