File writing

BlitzMax Forums/BlitzMax Beginners Area/File writing

(tu) ENAY(Posted 2005) [#1]
Hi,

I'm trying to read and write files but having some problems. I don't understand what I'm doing :) I can write one string to a file and saved but any more than that and I get an error.

Also with WriteString you have to specify the size of a string you're passing. Why is this? You didn't have to specify a size before.

I've got as far as Perturbatio's code here:-

http://www.blitzbasic.com/Community/posts.php?topic=47872&hl=WriteString

I simply just want to write a load of strings to a file and then read them back.

I can't see what was wrong with the old Blitz way of writing to files. It was definitely much less complicated.

Help! :)


WendellM(Posted 2005) [#2]
I simply just want to write a load of strings to a file and then read them back.

That's how I've always done my data files; I value easy human editability over compactness. :)

I just tested this, and the exact same approach I used in B3D works just fine in BlitzMax:
OutFile = WriteFile( "MyTest.txt" )
WriteLine OutFile, "Test string 1."
WriteLine OutFile, "And another one."
CloseFile OutFile

InFile = ReadFile( "MyTest.txt" )
While Not Eof( InFile )
	a$ = ReadLine( InFile )
	Print a$
Wend
Or are you needing something more advanced?


The r0nin(Posted 2005) [#3]
I think the issue arises for most beginners the first time that you want to read in the contents of a file with multiple lines of strings and load them into particular variables (like a config or ini file is normally used). It's the sorting or finding the right values that make the process complicated (that's why I use a standardized format with key-characters to make it easier). Just printing out the input as you get it is easy. Finding the numerical value for "number of enemies" from the middle of the file and getting the number split from the string header is a little more challenging for beginners (though not too hard once you play with it for a while)...


kenshin(Posted 2005) [#4]
Here's a type I wrote for simple handling of config files:

	Import BRL.System														'Import BMax System Module
	Import PUB.Win32														'Import Public Win32 Module
	Import BRL.Keycodes														'Import BMax Keycodes Module
	Import BRL.LinkedList													'Import BMax LinkedList Module
	Import BRL.FileSystem													'Import BMax FileSystem Module
	Import BRL.Retro														'Import BMax Retro Module
	Import BRL.StandardIO
	
	Type TConfig

		Field CR:String
		Field Name:String
		
		Method Init ( )

			CR = Chr ( 13 ) + Chr ( 10 )
			If FileType ( CurrentDir ( ) + "/" + Name + ".cfg" ) = False
				CreateFile ( CurrentDir ( ) + "/" + Name + ".cfg" )
			EndIf

		End Method
		
		Method Write ( Entry:String, Contents:String )
		
			Local strm:TStream = OpenStream ( CurrentDir ( ) + "/" + Name + ".cfg", True, True )
			Local tempcfg:TList = New TList
			Local found = False
			Local result:String
			While ( Eof ( strm ) = False )
				Local tempstring:String = ReadLine$ ( strm )
				If tempstring [ .. Len ( Entry ) ] = Entry
					Local newstring:String = Entry + " = " + Contents
					tempcfg.AddLast newstring
					found = True
				Else
					tempcfg.AddLast tempstring
				EndIf
			Wend
			CloseStream ( strm )
			DeleteFile ( CurrentDir ( ) + "/" + Name + ".cfg" )
			CreateFile ( CurrentDir ( ) + "/" + Name + ".cfg" )
			strm = OpenStream ( CurrentDir ( ) + "/" + Name + ".cfg", True, True )
			For Local t$ = EachIn tempcfg
				WriteLine ( strm, t )
			Next
			If found = False
				WriteString ( strm, Entry + " = " + Contents + CR )
			EndIf
			CloseStream ( strm )
			
		End Method
		
		Method Read:String ( Entry:String, DefaultContents:String )
			
			Local strm:TStream = OpenStream ( CurrentDir ( ) + "/" + Name + ".cfg", True, True )
			Local found = False
			Local result:String
			While ( Eof ( strm ) = False ) And ( found = False )
				Local tempstring:String = ReadLine$ ( strm )
				If tempstring [ .. Len ( Entry ) ] = Entry
					result = tempstring [ Len ( Entry ) + 3 .. ]
					found = True
				EndIf
			Wend
			CloseStream ( strm )
			If found = False
				strm = OpenStream ( CurrentDir ( ) + "/" + Name + ".cfg", True, True )
				SeekStream ( strm, StreamSize ( strm ) )
				WriteString ( strm, Entry + " = " + DefaultContents + CR )
				result = DefaultContents
				CloseStream ( strm )
			EndIf
			Return result
	
		End Method
		
	End Type
	
Config:TConfig = New TConfig
Config.Name = "Display"
Config.Init ( )
Config.Write ( "Res.X", String ( 800 ) )
Config.Write ( "Res.Y", String ( 600 ) )
print Int ( Config.Read ( "Res.X", "" ) )




Note that the Read method can also be used to add new entry's. If it finds that the entry does not exist, then it will create the entry and fill it with DefaultContents. If the entry already exists then it will return the current contents. If you want to change the contents just use the Write method.

It's not optimized for speed or massive config files as I didn't need these qualities for the project I am using it in.

Hope this helps.


(tu) ENAY(Posted 2005) [#5]
CHeers for the help guys :)

I'm well on my way now. I think the command I was looking for is WriteLine and not WriteString. Nice code Kenshin.

BTW Did you know that Kenshin is Japanese for medical examination? :)


kenshin(Posted 2005) [#6]
Nope, how do I change my name...:) I guess it depends on who I'm examining ;)

I had probs with the WriteString/WriteLine thing too.

Thx for the comment about my code. I'm fairly new to the OOP stuff so I've been spending a lot of time getting my head around it and finding a code layout which I can still read.