Dumb question

BlitzMax Forums/BlitzMax Beginners Area/Dumb question

I don't know if this is possible.

But, can you delete bytes of data from a file?

This is a function of my scoring system:


Function AddToHS(name:String,points:Int)
	Local file:TStream = WriteFile("hs.data")
		
		WriteString(file,name)
		WriteInt(file,points)
	
	CloseFile(file)

End Function



I want a remove function aswell, but i'm stumped.

I can find the specific name like so:

	Local name:String, myname:string = "bla"
	Local file:TStream = ReadFile("hs.data")
	While Not Eof(file)
		
		name = ReadString(file,3)
		points = ReadInt(file)
'???
'???
	If name = myname
'???
'???

	Wend
	CloseFile(file)


but then how would I remove it?

Thanks in advance!

can you delete bytes of data from a file?

Not likely.
You could blank them out, sure, but to shrink a file, I don't think so.

When writing to your "new" file, you can of course, choose to skip writing some data, in which case the file will shrink ;-)

And you might ignore data as you read it from the file.

But you can't really resize a pre-existing file.

There are two ways to go about it. If the file is small enough, then read the data into memory. Modify it however you want, then write the modified data back to the harddrive.
If it's too large for using memory, then open the file for reading, open a temporary file for writing. You then copy over whatever data you need to to the temp file. Then delete the original, and rename the temp file.

right, but how would you get rid of it in memory?

Would you like use an array of ints then find the int you wish to erase (same with strings) and set it to null?

Ok, i'm stumped again, I though maybe it was something with my program, so i wrote a seperate program to debug a high score system...

Can someone tell me what i'm doing wrong?:

Global FileMemoryList:TList = CreateList()

Type TFileMemory
	Field initals:String, points:Int
	
	Method AddToList:TFileMemory()
		ListAddLast(FileMemoryList,Self)
	End Method
	
	Method RemoveFromList:TFileMemory()
		FileMemoryList.Remove(Self)
	End Method
	
End Type


Function AddHS(i:String,p:Int)

	If Len(i) > 3
		Return
	End If
	
	Local file:TStream = OpenFile("hs.data")
	
	WriteString(file,i)
	WriteInt(file,p)
	
	CloseFile(file)

End Function

Function ReadHS()
	Local filestore:TFileMemory
	Local file:TStream = ReadFile("hs.data")
		While Not Eof(file)
		
			filestore:TFileMemory = New TFileMemory
			filestore.AddToList()
			filestore.initals = ReadString(file,3)
			filestore.points = ReadInt(file)
			
			Print "High Score: "+filestore.initals+" "+filestore.points+" Points"
		
		Wend
	
	CloseFile(file)
	FileMemoryList.Clear()
End Function

Function RemoveHS(i:String)

	Local filestore:TFileMemory
	Local file:TStream = ReadFile("hs.data")
		While Not Eof(file)
		
			filestore = New TFileMemory
			filestore.AddToList()
			filestore.initals = ReadString(file,3)
			filestore.points = ReadInt(file)
			
			If filestore.initals = i
				filestore.RemoveFromList()
			End If
			
			
		
		Wend
	
	CloseFile(file)
	
	file = WriteFile("hs.data")
		For Local b:TFileMemory = EachIn FileMemoryList
			WriteString(file,b.initals)
			WriteInt(file,b.points)
		Next
	CloseFile(file)
End Function

Function ClearHS()
	Local file:TStream = WriteFile("hs.data")
	CloseFile(file)
End Function


Print ""
Print "Making 3 Highscores, bri 12, str 15, and evr 13..."
AddHS("bri",12)
AddHS("str",15)
AddHS("evr",13)
Print ""
Print "Reading High score file..."
ReadHS()
Print ""
Print "Deleting bri's highscore..."
RemoveHS("bri")
Print ""
Print "Reading High score file..."
ReadHS()
Print ""
Print "Clearing File..."
ClearHS()

End


heres what I get:

Making 3 Highscores, bri 12, str 15, and evr 13...

Reading High score file...
High Score: evr 13 Points

Deleting bri's highscore...

Reading High score file...
High Score: evr 13 Points

Clearing File...


Its apparent that the problem either sits within the ReadHS() function or the AddHS() function.. But both look correct.

Whats suppost to happen is:

1. It makes 3 Highscores, bri 12, str 15, and evr 13...
2. It reads the high scores and prints the result - DOES NOT WORK CORRECTLY
3. It deletes bri's HS by loading into memory editing, and writing the file back out.
4. It reads the high scores again, this time it should be missing bri's - THIS DOES NOT WORK

Its only printing evr's HS.

Anyone know whats wrong?

PS. To run the program you need to save the source then make a notepad file named "hs.data" in the same directory, empty of course.

Every time you use OpenStream(), the original contents get erased. That's why only one score remains, the last one you add.
What you need to do is store the high scores in memory, and then write the contents to the HD in one go.

What part are you refering to? thats what I do with the remove function,


1. reads the file
2. stores in memory
3. edits memory file (removes the requested name)
4. writes the memory file out

I'm talking about when you first write the file to the hard drive in the AddHS() function. When you open the file and write the next high score, it erases the first one you wrote.
Although in testing, I discovered that the contents are not immediately erased, so you can seek to the end of the file before writing the next high score which will then append the next line.
SuperStrict
Global FileMemoryList:TList = CreateList()

Type TFileMemory
	Field initals:String, points:Int
	
	Method AddToList:TFileMemory()
		ListAddLast(FileMemoryList,Self)
	End Method
	
	Method RemoveFromList:TFileMemory()
		FileMemoryList.Remove(Self)
	End Method
	
End Type


Function AddHS(i:String,p:Int)

	If Len(i) > 3
		Return
	End If
	
	Local file:TStream = OpenFile("hs.data",True,True)
	SeekStream(file,StreamSize(file)) 'seek to end of file
	
	WriteString(file,i)
	WriteInt(file,p)
	
	CloseFile(file)

End Function

Function ReadHS()
	Local filestore:TFileMemory
	Local file:TStream = ReadFile("hs.data")
		While Not Eof(file)
		
			filestore:TFileMemory = New TFileMemory
			filestore.AddToList()
			filestore.initals = ReadString(file,3)
			filestore.points = ReadInt(file)
			
			Print "High Score: "+filestore.initals+" "+filestore.points+" Points"
		
		Wend
	
	CloseFile(file)
	FileMemoryList.Clear()
End Function

Function RemoveHS(i:String)

	Local filestore:TFileMemory
	Local file:TStream = ReadFile("hs.data")
		While Not Eof(file)
		
			filestore = New TFileMemory
			filestore.AddToList()
			filestore.initals = ReadString(file,3)
			filestore.points = ReadInt(file)
			
			If filestore.initals = i
				filestore.RemoveFromList()
			End If
			
			
		
		Wend
	
	CloseFile(file)
	
	file = WriteFile("hs.data")
		For Local b:TFileMemory = EachIn FileMemoryList
			WriteString(file,b.initals)
			WriteInt(file,b.points)
		Next
	CloseFile(file)
End Function

Function ClearHS()
	Local file:TStream = WriteFile("hs.data")
	CloseFile(file)
End Function


Print ""
Print "Making 3 Highscores, bri 12, str 15, and evr 13..."
AddHS("bri",12)
AddHS("str",15)
AddHS("evr",13)
Print ""
Print "Reading High score file..."
ReadHS()
Print ""
Print "Deleting bri's highscore..."
RemoveHS("bri")
Print ""
Print "Reading High score file..."
ReadHS()
Print ""
Print "Clearing File..."
ClearHS()

End

Notice the change I made in AddHS().
Your remove function works just fine once that change is made.

Wierd, i'd imagine it would automaticly seek itself to the end of the data it just inserted, and then add more? After all, it's a "OpenFile" not a "WriteFile"

Thanks for the help anyways!

New problem, when I want to display these high scores, i want them to be in order...

So, i turned to list sorting (never tried it before, but it beats coming up with your own sorting function)

Anyways, its not working, and my lack of knowlege of it is sucking at the moment.

anyways heres the code... modifications are under the ReadHS() function and a new method under TFileMemory:


SuperStrict
Global FileMemoryList:TList = CreateList()

Type TFileMemory
	Field initals:String, points:Int
	
	Method AddToList:TFileMemory()
		ListAddLast(FileMemoryList,Self)
	End Method
	
	Method RemoveFromList:TFileMemory()
		FileMemoryList.Remove(Self)
	End Method
	
	'.............................MOD
	Method Compare:Int(p:Object)
		Local pr:TFileMemory = TFileMemory(p)
		
		If(Self.points < pr.points) Then
			Return True
		Else 
			Return False
		End If
	End Method
	'..............................End mod
End Type


Function AddHS(i:String,p:Int)

	If Len(i) > 3
		Return
	End If
	
	Local file:TStream = OpenFile("hs.data",True,True)
	SeekStream(file,StreamSize(file)) 'seek to end of file
	
	WriteString(file,i)
	WriteInt(file,p)
	
	CloseFile(file)

End Function

Function ReadHS()
	Local filestore:TFileMemory
	Local file:TStream = ReadFile("hs.data")
		While Not Eof(file)
		
			filestore:TFileMemory = New TFileMemory
			filestore.AddToList()
			filestore.initals = ReadString(file,3)
			filestore.points = ReadInt(file)
		
		Wend
		'...........................................MOD
		FileMemoryList.Sort()
		For Local i:TFileMemory = EachIn FileMemoryList
			Print "High Score: "+filestore.initals+" "+filestore.points+" Points"
		Next
		'...........................................END MOD
	CloseFile(file)
	FileMemoryList.Clear()
End Function

Function RemoveHS(i:String)

	Local filestore:TFileMemory
	Local file:TStream = ReadFile("hs.data")
		While Not Eof(file)
		
			filestore = New TFileMemory
			filestore.AddToList()
			filestore.initals = ReadString(file,3)
			filestore.points = ReadInt(file)
			
			If filestore.initals = i
				filestore.RemoveFromList()
			End If
			
			
		
		Wend
	
	CloseFile(file)
	
	file = WriteFile("hs.data")
		For Local b:TFileMemory = EachIn FileMemoryList
			WriteString(file,b.initals)
			WriteInt(file,b.points)
		Next
	CloseFile(file)
End Function

Function ClearHS()
	Local file:TStream = WriteFile("hs.data")
	CloseFile(file)
End Function


Print ""
Print "Making 3 Highscores, bri 12, str 15, and evr 13..."
'un sorted as you can see....
AddHS("bri",4)
AddHS("str",77)
AddHS("evr",2)
Print ""
Print "Reading High score file..."
'this function should sort them aswell (by points)
ReadHS()
Print ""
Print "Deleting bri's highscore..."
RemoveHS("bri")
Print ""
Print "Reading High score file..."
ReadHS()
Print ""
Print "Clearing File..."
ClearHS()

End


here's my debug session, It's behaving similar to before, only printing the last entry, but its printing it 3 times like there is 3 highscores there (which is correct)... then after deleting bri's, it prints it 4 times (whhhaaat...?)

Reading High score file...
High Score: evr 2 Points
High Score: evr 2 Points
High Score: evr 2 Points

Deleting bri's highscore...

Reading High score file...
High Score: evr 2 Points
High Score: evr 2 Points
High Score: evr 2 Points
High Score: evr 2 Points


also, this is my reference to how TLists sort, though its kinda old, and might be changed:
http://www.blitzbasic.com/Community/posts.php?topic=50278


Thanks in advance!

That's because in your ReadHS() function, you loop through the FileMemoryList, storing the object in i, but then printing the contents of filestore.
	For Local i:TFileMemory = EachIn FileMemoryList
			'Print "High Score: "+filestore.initals+" "+filestore.points+" Points" change to
	
			Print "High Score: "+i.initals+" "+i.points+" Points"
		Next

Also there is another bug in your ReadHS() and RemoveHS() routine. You read in the highscore list and add it to the end of the already filled list. You need to do a FileMemoryList.Clear() at the start of the functions to erase the contents.

Ahh, that was stupid, i hate it when you go to hell and back to fix a problem and its right under your nose -.-