How do I read from a config file

Blitz3D Forums/Blitz3D Programming/How do I read from a config file

Say I have a config file like the below:
Lives=5
Gravity=9.7
Language=English



And so on, how do I read values from that file and also write values back into it?

several examples in the code archives.

here is one:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1754

thanks, I'll check them out

Here is what I use for my config files.
Make a config.ini file that contains this
---screen resolution
screen_w=1024
screen_h=768
fullscreen=1

---Player 1 controls
P1_up=200
P1_down=208
P1_left=203
P1_right=205
P1_fire=57
P1_accel=29
P1_reverse=56 


Now the code part. What I do is assign every variable a "default" value, and then call the readconfig() function. This way I know that all values are correctly assigned in case the config file is missing/wrong. You should also check the read values to make sure they are "legal" for whatever they are being assigned.

Note that anything that is not an explicitly stated variable is simply ignored, so you can easily add comments.

;Ini Variables
Global screen_w = 640
Global screen_h = 480
Global fullscreen = 0

Global P1_up = 200
Global P1_down = 208
Global P1_left = 203
Global P1_right = 205
Global P1_fire = 57
Global P1_accel = 29
Global P1_reverse =56 

readconfig()
printvalues()
;writeconfig()
WaitKey
End 

Function Printvalues()
Print "Screen width: " + screen_w
Print "Screen height: " +screen_h
Print "fullscreen: " + fullscreen

Print "P1 up: " + P1_up
Print "P1 down: " + P1_down
Print "P1 left: " + P1_left
Print "P1 right: " + P1_right
Print "P1 fire: " + P1_fire
Print "P1 accel: " + P1_accel
Print "P1 reverse: " + P1_reverse 

End Function

Function ReadConfig()
	Local label$
	Local value
	Local location

	filename = ReadFile ("config.ini")	;load the config file
	If filename <> 0								;only continue if the file exists
		While Not Eof (filename)				;keep reading until the end of the file
			val$ = ReadLine(filename)		;read the full line
				location = Instr( val$,"=",1)	;find the location of the = sign
				If Not location = 0				;if no = found in the line, ignore it.
					label$ =  Left$ (val$, location-1)			; get the label part of the line
					value = Int( Right$ (val$, Len(val$) -location))	;get the value part of the line
					Select True
						Case label$ = "screen_w"
							screen_w = value
						Case label$ = "screen_h"
							screen_h = value
						Case label$ = "fullscreen"
							fullscreen = value
						Case label$ = "P1_up"
							P1_up = value
						Case label$ = "P1_down"
							P1_down = value				
						Case label$ = "P1_left"
							P1_left = value
						Case label$ = "P1_right"
							P1_right = value
						Case label$ = "P1_fire"
							P1_fire = value
						Case label$ = "P1_accel"
							P1_accel = value	
						Case label$ = " P1_reverse"
							P2_reverse = value	
						Default ; no known variable, so do nothing.
					End Select	
				EndIf
		Wend

		CloseFile (filename)	; all done reading, so close the file
		info$ = "config file opened"
	Else ; file does not exist, take alternative action
		info$ = "load failed, or no .cfg file present"
	EndIf 
End Function 

Function writeconfig()
	filename = WriteFile ("config2.ini")

	WriteLine (filename, "---screen resolution")
	WriteLine (filename, "screen_w=" + Str(screen_w))
	WriteLine (filename, "screen_h=" + Str(screen_h))
	WriteLine (filename, "fullscreen=" + Str(fullscreen))
	WriteLine (filename, " ")
	WriteLine (filename, "---Player 1 controls")	
	WriteLine (filename, "P1_up=" + Str(P1_up))
	WriteLine (filename, "P1_down=" + Str(P1_down))
	WriteLine (filename, "P1_left=" + Str(P1_left))
	WriteLine (filename, "P1_right=" + Str(P1_right))
	WriteLine (filename, "P1_fire=" + Str(P1_fire))
	WriteLine (filename, "P1_accel=" + Str(P1_accel))
	WriteLine (filename, "P1_reverse=" + Str(P1_reverse)) 

	CloseFile( filename )
End Function 



I'd suggest encrypting (simply exchanging every character using a value or something) so as to not have people messing with the config files (except for what you want to let them manipulate). So as to keep smart guys from typing in "lives=99999".

Here's some excample code of 2 functions I am using in a project which do exactly that:


(Note that the variables will need to be declared as global in the main prog)

fCONFIGFILE$ can be a constant, but needs to be the complete path & filename to the Configuration file.

Also, remember to specify whether Floats, Integers or Strings and use the correct notation (i.e. # $ etc.) else you may get errors.

Function LoadConfigs()
ConfigFile=OpenFile(fCONFIGFILE$)
	
;	Debug("INITIALISING","SETTING CONFIGURATION")

;If ConfigFile=0
	
;		Debug("INITIALISING","INSTALLATION CORRUPT. CONFIGURATION FILE NOT FOUND")
	
;	ExitApplication("INSTALLATION CORRUPT. CONFIGURATION FILE NOT FOUND")
	
;End If


HI_SCORE=ReadInt(ConfigFile)
INITIALS$=ReadString$(ConfigFile)
FXVOL#=ReadFloat#(ConfigFile)
MUSICVOL#=ReadFloat#(ConfigFile)
RESX=ReadInt(ConfigFile)
RESY=ReadInt(ConfigFile)
RESZ=ReadInt(ConfigFile)
FULLSCREEN=ReadInt(ConfigFile)
FSAA=ReadInt(ConfigFile)
DITHERING=ReadInt(ConfigFile)
WIRED=ReadInt(ConfigFile)
W_BUFFER=ReadInt(ConfigFile)
HW_TEXT=ReadInt(ConfigFile)
GRAPH_SET=ReadInt(ConfigFile)
CloseFile ConfigFile
End Function

;---------------------------------

Function SaveConfigs()

;		Debug("SAVING CONFIGURATIONS","START")
;		Debug("SAVING CONFIGURATIONS","DELETE OLD FILE: "+fCONFIGFILE$)
				
	DeleteFile fCONFIGFILE$
				
	ConfigFile=WriteFile(fCONFIGFILE$)

	WriteInt(ConfigFile,HI_SCORE)
	WriteString( ConfigFile,INITIALS$ )
	WriteFloat( ConfigFile,FXVOL# )
	WriteFloat( ConfigFile,MUSICVOL# )
	WriteInt( ConfigFile,RESX )
	WriteInt( ConfigFile,RESY )
	WriteInt( ConfigFile,RESZ )
	WriteInt( ConfigFile,FULLSCREEN )
	WriteInt( ConfigFile,FSAA )
	WriteInt( ConfigFile,DITHERING)
	WriteInt( ConfigFile,WIRED )
	WriteInt( ConfigFile,W_BUFFER )
	WriteInt( ConfigFile,HW_TEXT)
	WriteInt( ConfigFile,GRAPH_SET)
	
	CloseFile ConfigFile

End Function



I'd suggest encrypting (simply exchanging every character using a value or something) so as to not have people messing with the config files (except for what you want to let them manipulate). So as to keep smart guys from typing in "lives=99999".
The whole point of a config file is to allow the user to configure things. Clue's in the name. ;)

If you have data you don't want the user to mess with, it has no business being in a config file.

Too right.
I depend on being able to modify the config file in case there's issues with the screen resolution :D

If you have data you don't want the user to mess with, it has no business being in a config file.

So you'd rather have an in-game element like "amount of lives" or other console-like settings exposed so the user can put whatever value he wants?

Regarding things like resolution, graphic features and gameplay elements you could have a modifiable .txt or .cfg file, I agree with you on that.

But when it comes to settings like lives available, amount of items around the level etc, you should encrypt it (if you wish to be able to modify it say, dinamically according to player progress. If you already have a fixed value for what you want you just place it in the code and compile it).

Or don't you think professional games don't have encrypted configuration files reserved for the software exclusively?

Thanks guys, I've implemented my config file using Pongo's code. I'm using it for screen resolution.
I've also got a whole load of other data, but that level dependant, so that goes into my level file structure.

Kryzon,... I think there is a use for encrypted data, but generally a config file is set up so the user can change things. As the programmer you still have the ultimate control over that.

For example, you may have an option for number of lives in the config, but your code can read the value and only use a hard-coded maximum if the value is way off.

You should really do this kind of thing anyways with a config file, since the user could enter something invalid that will screw up your code otherwise. If the user is allowed to enter screen resolutions, you should check that they are valid before setting the screen to that resolution. The same goes for any other value. I usually either clamp values at a minimum or max value, or simply ignore the config value if it is out of range and use a default instead.

Pongo...why the hell are you telling me that?

well seeing as andy was after a profile type set up, where you could have x gamers using the same pc at any given time (taking turns naturally). each would have their prefered screen res and controller method/keyboard layout

you were the first to bring up changing the lives in said file, no one in their right mind would stick lives/health/score and other player data in a config file of this type

all that is needed is
screen height
screen width
full screen/windowed

keyboard+mouse
pc joypad
360 joypad
ps3 joypad

user definable keys (also duals as joypad buttons)

nothing much if anything else is needed

so pongo and big10p are asking YOU why YOU think lives etc should be in THIS type of config file, something that is only meant to be game controlls and screen size.

other data files where lives/health/gold/score etc SHOULD be harder to suss out and not in a human readable format but "ijkl;er" or some other keyboard mash

no one in their right mind would stick lives/health/score and other player data in a config file of this type

Say I have a config file like the below:

Lives=5
Gravity=9.7
Language=English



You don't say.


so pongo and big10p are asking YOU why YOU think lives etc should be in THIS type of config file, something that is only meant to be game controlls and screen size.


I DON'T think a variable like that should be in a config file. But hey! look in the OP.


other data files where lives/health/gold/score etc SHOULD be harder to suss out and not in a human readable format but "ijkl;er" or some other keyboard mash


OK! you're just repeating what I said previously! Although that's COMPLETELY UNNECESSARY, no need to say anything.

Woah! Chill, guys. Andy got what he needed so all's good.


well seeing as andy was after a profile type set up, where you could have x gamers using the same pc at any given time (taking turns naturally). each would have their prefered screen res and controller method/keyboard layout

That was never actually mentioned so I for one had no idea he would want separate profiles for separate players.

The basic idea is the same, only the config file itself is either given a filename or placed in a separate ditrectory relevant to each gamer's profile. It is also recommended to maintain a hidden/default config and/or select the last config used.

ok i stand corrected on the first post
i seem to have gotten pongo's windows res super imposed on andy's in my brain when i re read it

That was never actually mentioned so I for one had no idea he would want separate profiles for separate players.

it might have been implied, or i read an extra post that only existed in my mind just as the first blanked itself out on me ;), its kinda what a console would do to an extent

OK! you're just repeating what I said previously! Although that's COMPLETELY UNNECESSARY, no need to say anything.


i think my brain is still lopsided from the dentist yesterday (or more lopsided than usual)
seems we were on the same page its just that mine had the first paragraph torn off ;)

i think my brain is still lopsided from the dentist yesterday (or more lopsided than usual)
seems we were on the same page its just that mine had the first paragraph torn off ;)

Hah no harm done :D

I hope everything went alright in there.

Cyou guys later!