FileStream

kurt69

Well-known member
Joined
Jan 17, 2006
Messages
78
Location
Australia
Programming Experience
Beginner
Hi again I feel so stupid posting another question up already. But with my game I have just written and designed the forms that will create a character and let you specify his statistics, names, sprite. Now I'm trying to make it so when you click Load character it will load a file called "characters.ini" which contains the name of the character and the path to it, for example:

Kurt
.\characters\Kurt.lfr

And then display this in a list in my program with just the name of the character, while storing the path to it in a variable. But also there could be many characters in the list.

So I'm guessing I need a code to parse the text, store the names in the list then the paths in an array variable? Any help, sample code would be greatly appreciated. Thanks.
 
I recommend you to use two arraylists

Private CharName As New ArrayList
Private CharFile As New ArrayList

when the user creates a new character you will add to these array
CharName.Add("a name")
CharFile.Add("some\filename\hey.lfr")

and use serialization to save and load these arrays to a file.

example to save to file
VB.NET:
[SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] strm [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IO.FileStream(Application.StartupPath & "\" & filename, IO.FileMode.OpenOrCreate)
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] BinFormatter [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Binary.BinaryFormatter
BinFormatter.Serialize(strm, CharName)
BinFormatter.Serialize(strm, CharFile)
strm.Close()
[/SIZE]

that saves your two arrays to a file, by opening a file stream and using serialize. With some googling you should be able to figure out how to deserialize
 
Ok i tried that method and I've run into a problem. I've set the IO.FileMode to Append because I don't want it to write over whats in there, but I'm getting the error: (Although when I built and ran the program it worked.)

Value of type 'String' cannot be converted to type 'System.Collections.ArrayList'

This is what I set the CharFile as:
VB.NET:
CharName = inpName.Text
CharFile = ".\characters\" & charName & ".lfr"

Contens of characters.ini:
VB.NET:
 ÿÿÿÿ  New Character  ÿÿÿÿ  .\characters\New Character.lfr

Edit: Anyway apart from that error I moved onto deserializing, This is what I have.

VB.NET:
[SIZE=2][COLOR=#0000ff]
Private[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] txtLoadChar_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] txtLoadChar.Click
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Sound [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] SoundPlayer("..\content\sounds\select.wav")
Sound.PlaySound()
GetObject()
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff][/COLOR][/SIZE] 
[/COLOR][/SIZE]
VB.NET:
[COLOR=#0000ff] [/COLOR]
Function[SIZE=2][COLOR=#000000] GetObject() [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#000000] [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Object
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] strm [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IO.FileStream(Application.StartupPath & "\" & "characters.ini", IO.FileMode.Append)
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] BinFormatter [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Serialization.Formatters.Binary.BinaryFormatter
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] charPath [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Object
[/COLOR][/SIZE][SIZE=2]charPath = BinFormatter.Deserialize(strm)
BinFormatter.Deserialize(strm)
strm.Close()
[/SIZE][SIZE=2][COLOR=#0000ff]Return[/COLOR][/SIZE][SIZE=2] charPath
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Function[/COLOR][/SIZE]
So what do I need to do now? Thanks.
 
Last edited:
you will have to overwrite the file, it doesnt work that way.
you save the arraylist object to file, and then you load it.. then you overwrite it again with the new updated arraylist.

if you use append.. you would end up storing multiple instances in the file.
 
Last edited:
I'm keeping this for posterity.
 

Attachments

  • Newbie.JPG
    Newbie.JPG
    3.5 KB · Views: 193
you almost got it,​
you are saving two arraylists to the file, so you need to deserialize two objects, and directcast them to their arraylist type
no need to use a function, your arrays should be declared on a form level, use a sub and just directly use them in the code.

one other error, you need to change the filestream mode to "Open" since you are opening the file not appending to it.

VB.NET:
Sub[SIZE=2][COLOR=#000000] GetObjects()[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] strm [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IO.FileStream(Application.StartupPath & "\" & "characters.ini", IO.FileMode.Open)
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] BinFormatter [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Serialization.Formatters.Binary.BinaryFormatter[/SIZE][SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2]CharName = DirectCast(BinFormatter.Deserialize(strm),ArrayList)[/SIZE]
[SIZE=2]CharFile = DirectCast(BinFormatter.Deserialize(strm),ArrayList)
[/SIZE]
[SIZE=2]
strm.Close()
[/SIZE][SIZE=2][COLOR=#0000ff]End Sub[/COLOR][/SIZE]

@Jm : damn you mr big shot moderator :p
 
I've never worked with ArrayLists before so I'm guessing if I want to keep what's already in the file I have to load it then add the new data into the ArrayLists then finally save.
 
that's right,

an Arraylist is an array of Objects (so anything can be stored in it) and its size expands and shrinks as needed, so you can .remove items or .add items to the array whenever you like.
 
Yeah so I'm lost I been workin at this for awhile. Sorry I'm not getting it but thats why im here.. i need help from people more proficient with vb.net/programming altogether.

Heres wat ive got:

VB.NET:
[SIZE=2][COLOR=#0000ff]
Private[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] btnSave_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] btnSave.Click
[/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] inpName.Text = "New Character" [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]MsgBox("Please type a name for your character.")
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] startstatsRemaining >= 0 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]charName = inpName.Text
savefileName = Application.StartupPath & "\Characters\" & charName & ".lfr"
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] fs [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] FileStream(savefileName, FileMode.Create, FileAccess.Write)
[/SIZE][SIZE=2][COLOR=#008000]'declaring a FileStream and creating a word document file named file with 
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#008000]'access mode of writing
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] s [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] StreamWriter(fs)
[/SIZE][SIZE=2][COLOR=#008000]'creating a new StreamWriter and passing the filestream object fs as argument
[/COLOR][/SIZE][SIZE=2]s.BaseStream.Seek(0, SeekOrigin.End)
[/SIZE][SIZE=2][COLOR=#008000]'the seek method is used to move the cursor to next position to avoid text to be
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#008000]'overwritten
[/COLOR][/SIZE][SIZE=2]s.WriteLine(charName)
s.WriteLine(attackStat)
s.WriteLine(defenseStat)
s.WriteLine(healthStat)
s.WriteLine(manaStat)
s.WriteLine(powerStat)
s.WriteLine(speedStat)
[/SIZE][SIZE=2][COLOR=#008000]'writing text to the newly created file
[/COLOR][/SIZE][SIZE=2]s.Close()
charName = inpName.Text
CharFile.Add(".\characters\" & charName & ".lfr")
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] strm [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IO.FileStream(Application.StartupPath & "\" & "characters.ini", IO.FileMode.OpenOrCreate)
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] BinFormatter [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Serialization.Formatters.Binary.BinaryFormatter
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] f [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IO.FileInfo(Application.StartupPath & "\" & "characters.ini")
[/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] f.Length > 1 = [/SIZE][SIZE=2][COLOR=#0000ff]True[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]charNameArray = [/SIZE][SIZE=2][COLOR=#0000ff]DirectCast[/COLOR][/SIZE][SIZE=2](BinFormatter.Deserialize(strm), ArrayList)
CharFile = [/SIZE][SIZE=2][COLOR=#0000ff]DirectCast[/COLOR][/SIZE][SIZE=2](BinFormatter.Deserialize(strm), ArrayList)
charNameArray.Add(inpName.Text)
CharFile.Add(".\characters\" & charName & ".lfr")
BinFormatter.Serialize(strm, charNameArray)
BinFormatter.Serialize(strm, CharFile)
strm.Flush()
strm.Close()
MsgBox("Your character has been created and saved.")
[/SIZE][SIZE=2][COLOR=#0000ff]Else[/COLOR][/SIZE][SIZE=2] : MsgBox("You have spent to many statistic points.")
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2] startstatsRemaining >= 0 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] strm [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IO.FileStream(Application.StartupPath & "\" & "characters.ini", IO.FileMode.OpenOrCreate)
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] BinFormatter [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Serialization.Formatters.Binary.BinaryFormatter
charNameArray.Add(inpName.Text)
CharFile.Add(".\characters\" & charName & ".lfr")
BinFormatter.Serialize(strm, charNameArray)
BinFormatter.Serialize(strm, CharFile)
strm.Flush()
strm.Close()
MsgBox("Your character has been created and saved.")
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE]

When I click save it gives me the error "the file is in use by another process" and when im trying to load it gives me the error that it is an empty stream, i tried to get around that with f.length > 1.
 
Ok.. what you need to do, is split your LOAD and SAVE methods into two different subs.. for starters that will make it ALOT easier for us to read.. i find it hard to follow your code, it is too bunched up.

I don't think you are understanding the concept though.
You only need to Load the file once.. that is, when your program starts up, Load event.. so that last you retrieve characters from when last time the game was run.. you no longer care about loading the file from this point.

same goes for save, you only need to save the file when nothing else is going to be added, the arraylists do not depend on the file.. they are normal objects that operate on their own, we just use serialize to remember them for next time the program runs.

so the ideal time to save your arrays is when the user either quits, or starts the game (in other words, has exited the screen where they can add or modify characters)
 
Ohhhhhhhh Ok yeah I should've realised load on start. Silly me :), things get overlooked when your trying to work something out though. I did actually have my load and save codes in two different subs, one where they click Load Characters and one where they click Save Characters but i only showed you the save. I'm going to change my load thing to form onload. Whats with the file being used by another process though, Oh i just realised i have to close the load stream first before i save, dammit.

edit: ok works like a charm so far. now i just have to make it so it shows the names in a listbox, and clicking them will link them to load the characters save file and its variables. i'll have a go at it but most likely ill be back with more questions, lets hope not.

update: i now have the listbox displaying all elements in the array list, but i had to convert the array list to an array and then addrange to the listbox, i hope thats the right way of doing it.
 
Last edited:
hey again, it's been awhile.

umm, anyway I've been trying to make it so when they press the load character button it loads the character they have selected in the list box below it. here's my code, what am i doing wrong.

VB.NET:
[SIZE=2]charName = loadcharList.SelectedItem
savefileName = ".\characters\" & charName & ".lfr"[/SIZE]
Dim strm As New IO.FileStream(savefileName, IO.FileMode.Open)
Dim BinFormatter As New Serialization.Formatters.Binary.BinaryFormatter
attackStat = DirectCast(BinFormatter.Deserialize(strm), Integer)
defenseStat = DirectCast(BinFormatter.Deserialize(strm), Integer)
healthStat = DirectCast(BinFormatter.Deserialize(strm), Integer)
manaStat = DirectCast(BinFormatter.Deserialize(strm), Integer)
powerStat = DirectCast(BinFormatter.Deserialize(strm), Integer)
speedStat = DirectCast(BinFormatter.Deserialize(strm), Integer)
strm.Close()
Dim frmNew As New frmMain
frmNew.Show()
Me.Hide()

I'm pretty sure its the:
charName = loadcharList.SelectedItem
that i've done wrong. it doesn't give me an error, but the variables dont change from their default value to the value im trying to load.
 
instead of having all those integers, you should have a structure, or a character class, which contain all those integers, so you only serialize 1 character object.

selecteditem is correct, what is your actual error..
 
Uh sorry phill, I got back on just now to delete my post. I had a good hard long look at my code and realised.. I had an update timer which grabbed the numbers from the input text boxes which was overriding the loaded variable, which made it seem like it wasn't loading. Sorry about this.

Oh and thanks heaps for your help with this overall, your a champ.
 
Back
Top