What's a good general algorithm for parsing ini files?

igowerf

Diamond Member
Jun 27, 2000
7,697
1
76
I've always written some crappy, unflexible code to load values from ini files (or just text files in general). I was wondering if there's a good, general method to doing it.

Right now, I'm actually looking for something in VB, but any language would work, as long as I can understand it. If you're going to post some complicated, huge ass, string parsing expression, please at least explain it for me. :p (notfred and BingBongWongFooey specifically)
 

notfred

Lifer
Feb 12, 2001
38,241
4
0
I just looked through a bunch of .ini files in c:/WINNT, and none of them seems to share any particular format. Got an example file?
 

naddicott

Senior member
Jul 3, 2002
793
0
76
Interesting question. I would look into and share the approach we use at my workplace, except I'm fairly certain that the relevant code is considered proprietary. That and it may well be just as crappy and unflexible as the code you're already using. :p
 

Descartes

Lifer
Oct 10, 1999
13,968
2
0
No need to reinvent the wheel, the Win32 API already has facilities that encapsulate access to INI files. Considering Windows has been using INI files since 3.0, this is not a surprise. Look here for GetPrivateProfileString and friends. If you need some sample VB code, I can pull up some of my old stuff. Google I'm certain can provide you with many examples as well.
 

Barnaby W. Füi

Elite Member
Aug 14, 2001
12,343
0
0
Python has a module called ConfigParser which reads and writes .ini-style files, with python % string substitution ( i.e. setting = %(othersetting)s ), and it'll write your changed values back to the file for you and everything. I use it myself, works very well.
 

Barnaby W. Füi

Elite Member
Aug 14, 2001
12,343
0
0
the file "foo.config":
[DEFAULT]
foo: bar
a: b
c: hey there

[hello]
goodbye: true
abc: %(a)s

And a tiny hello-world-ish script to grab info from it:
import ConfigParser

parser = ConfigParser.ConfigParser()

parser.read("foo.config")

print parser.defaults()
print parser.sections()

print parser.options("hello")

 

notfred

Lifer
Feb 12, 2001
38,241
4
0
Ok, here's my solution. I wrote a perl script that takes 1 command line argument (i.e. run "testini.pl c:\winnt\win.ini").

The script is here

I tested it with this file from my machine

And the output I got from running the script is shown here:

C:\>testini.pl c:/WINNT/win.ini
[MCI Extensions.BAK]
mp3=MPEGVideo
m3u=MPEGVideo
asf=MPEGVideo
wm=MPEGVideo
wma=MPEGVideo
asx=MPEGVideo
wax=MPEGVideo
wpl=MPEGVideo
wmv=MPEGVideo
wvx=MPEGVideo
mpv2=MPEGVideo
ivf=MPEGVideo
mp2v=MPEGVideo
wmx=MPEGVideo2

[WS_FTP]
GROUP=WS_FTP Pro
DIR=C:\Program Files\WS_FTP Pro

[SciCalc]
layout=0

[MSUCE]
Font=Arial
CodePage=Unicode
Advanced=0

[title]

[Mail]
MAPI=1

[Tera Term Pro]
Path=C:\PROGRAM FILES\TTERMPRO


How's that?
 

DT4K

Diamond Member
Jan 21, 2002
6,944
3
81
Well, this may be just as crappy and inflexible as what you currently do, but here is the code we have been using without issue for the last few apps. We keep the db connection info in an ini so it can be pointed at either the test or production server by changing the ini.


This is code from the main form's load event:

'Get SQL Server database and server names from .ini
Open INI_FILE_PATH For Input As #1
Do While Not EOF(1)
'Read one line from the ini file
Input #1, strTemp
'Ignore case and leading whitespace
strTemp = UCase(Trim(strTemp))
'Check for blank lines or comment lines
If strTemp <> "" And Left(strTemp, 2) <> "//" Then
'Get the value and put it in the appropriate global variable
Select Case Left(strTemp, 4)
Case Is = "DATA"
gstrSQLDataSource = GetINIValue(strTemp)
Case Is = "INIT"
gstrSQLInitialCatalog = GetINIValue(strTemp)
Case Is = "LABE"
gstrLabelPrinter = GetINIValue(strTemp)
End Select
End If
Loop
Close #1

And here is the function code:

Private Function GetINIValue(strStringToParse As String)
Dim intStartingPoint As Integer, i As Integer, intAsciiCode As Integer

For i = 1 To Len(strStringToParse)
'Get the ascii code for the character
intAsciiCode = Asc(Mid(strStringToParse, i, 1))
'If it's not a space or alphanumeric character, replace it with a space
If intAsciiCode < 33 Or intAsciiCode > 126 Then Mid(strStringToParse, i, 1) = " "
Next i

'find the ":" in the string
intStartingPoint = InStr(1, strStringToParse, ":")
If intStartingPoint > 0 Then
'Get the value to the right of the colon
GetINIValue = Trim(Mid(strStringToParse, intStartingPoint + 1))
Else
GetINIValue = ""
End If

End Function

And here is what our ini file looks like:
//kwc.ini
//This configuration file specifies DB connection information used by applications
//Any lines beginning with // are treated as comments and will be ignored by the applications

//Test instance
//data source :servername\instancename
//initial catalog :Dbname

//Production instance
data source :servername\instancename
initial catalog :Dbname

//Label printer setup
label printer :\\printserver\printername
 

Barnaby W. Füi

Elite Member
Aug 14, 2001
12,343
0
0
Why parse it by hand? As Descartes mentioned, the ini format is pretty old, and MS has already done the parsing work for you. Reinventing the wheel, tisk tisk. ;)
 

DT4K

Diamond Member
Jan 21, 2002
6,944
3
81
Originally posted by: BingBongWongFooey
Why parse it by hand? As Descartes mentioned, the ini format is pretty old, and MS has already done the parsing work for you. Reinventing the wheel, tisk tisk. ;)
You of all people, advocating the use of code that MS has done for us ?


;)