Ooops
April 04, 2020, 04:14:32 PM

Author Topic: [bmx] Read/Write INI File (BMX) by Perturbatio [ 1+ years ago ]  (Read 4170 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Read/Write INI File (BMX)
Author : Perturbatio
Posted : 1+ years ago

Description : Simple INI file reader/writer

Code :
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Function SplitString:TList(inString:String, Delim:String)
  4.         Local tempList : TList = New TList
  5.         Local currentChar : String = ""
  6.         Local count : Int = 0
  7.         Local TokenStart : Int = 0
  8.        
  9.         If Len(Delim)<1 Then Return Null
  10.        
  11.         inString = Trim(inString)
  12.        
  13.         For count = 0 Until Len(inString)
  14.                 If inString[count..count+1] = delim Then
  15.                         tempList.AddLast(inString[TokenStart..Count])
  16.                         TokenStart = count + 1
  17.                 End If
  18.         Next
  19.         tempList.AddLast(inString[TokenStart..Count])  
  20.         Return tempList
  21. End Function
  22.  
  23.  
  24. Type TIniSection
  25.         Field Name:String
  26.         Field Values:TMap
  27.        
  28.        
  29.         Method SetValue(key:String, value:Object)
  30.                 Values.Insert(Key, Value)
  31.         End Method
  32.        
  33.        
  34.         Method GetValue:String(Key:String)
  35.                 Return String(Values.ValueForKey(Key))
  36.         End Method
  37.        
  38.        
  39.         Method DeleteValue(Key:String)
  40.                 Values.Remove(Key)
  41.         End Method
  42.        
  43.        
  44.         Method GetSectionText:String()
  45.                 Local result:String = "["+Name+"]~r~n"
  46.                
  47.                 For Local s:Object = EachIn Values.keys()
  48.                         result = result + String(s) + "=" + String(Values.ValueForKey(s)) + "~r~n"
  49.                 Next
  50.                
  51.                 Return result+"~r~n"
  52.         End Method
  53.        
  54.        
  55.         Function Create:TIniSection(name:String)
  56.                 Local tempSection:TIniSection = New TIniSection
  57.                         tempSection.name = name
  58.                         tempSection.Values = New TMap
  59.                 Return tempSection
  60.         End Function
  61.        
  62. End Type
  63.  
  64.  
  65.  
  66. Type TSectionList
  67.         Field _Sections:TIniSection[]
  68.        
  69.         Method GetSection:TIniSection(sectionName:String)
  70.        
  71.                 For Local section:TIniSection = EachIn _Sections
  72.                         If section.Name = sectionName Then Return section
  73.                 Next
  74.                
  75.                 Return Null
  76.                
  77.         End Method
  78.        
  79.        
  80.         Method AddSection:TIniSection(sectionName:String)
  81.                 Local currentLength:Int = Len(_Sections)
  82.                
  83.                         _Sections = _Sections[..currentLength+1]
  84.                         _Sections[currentLength] = TIniSection.Create(sectionName)
  85.                
  86.                 Return _Sections[currentLength]
  87.         End Method
  88.        
  89.        
  90.         Method RemoveSection:Int(sectionName:String)
  91.                 Local currentLength:Int = Len(_Sections)
  92.                
  93.                 For Local i:Int = 0 To currentLength-1
  94.                         If _Sections[i].Name = sectionName Then
  95.                                 If i < currentLength-1 Then
  96.                                         For Local x:Int = i To currentLength-2
  97.                                                 _Sections[x] = _Sections[x+1]
  98.                                         Next
  99.                                 EndIf
  100.                                 _Sections = _Sections[..currentLength-1]
  101.                                
  102.                                 Return True
  103.                                
  104.                         EndIf
  105.                 Next
  106.                
  107.                 Return False
  108.         End Method
  109.        
  110.        
  111.         Function Create:TSectionList()
  112.                 Local tempSectionList:TSectionList = New TSectionList
  113.                        
  114.                 Return tempSectionList
  115.         End Function
  116.        
  117. End Type
  118.  
  119.  
  120.  
  121. Type TPertIni
  122.         Field Filename:String
  123.         Field Loaded:Int
  124.         Field Saved:Int
  125.         Field Sections:TSectionList
  126.        
  127.        
  128.         Method Load:Int()
  129.                 Local file:TStream
  130.                 Local line:String
  131.                 Local tempList:TList
  132.                 Local tempArray:Object[]
  133.                 Local currentSection:String = ""
  134.                 Local error:String
  135.                
  136.                
  137.                 If FileType(Filename) = 1 Then
  138.  
  139.                         file:TStream = ReadStream(FileName)
  140.                        
  141.                         While Not Eof(file)
  142.                                
  143.                                 line = Trim(ReadLine(file))
  144.                                
  145.                                
  146.                                
  147.                                 If Not (Line[..1] = ";") Then
  148.                                        
  149.                                         If Line[..1] = "[" And Line[Len(Line)-1..] = "]" Then
  150.                                                 currentSection = Line[1..Len(Line)-1]
  151.                                                
  152.                                                 AddSection(currentSection)
  153.                                         Else
  154.                                                 If Len(currentSection) > 0 And Len(line) > 0 Then
  155.                                                         tempList = SplitString(Line, "=")
  156.                                                         If tempList Then
  157.                                                                 tempArray = tempList.ToArray();
  158.                                                                 SetSectionValue(currentSection, String(tempArray[0]), String(tempArray[1]))
  159.                                                         EndIf
  160.                                                 Else If Len(Line) > 0 Then
  161.                                                         Return False 'no section header found'
  162.                                                 EndIf
  163.                                         EndIf
  164.                                 EndIf
  165.                         Wend
  166.                        
  167.                         CloseStream(file)
  168.                
  169.                 EndIf
  170.                
  171.                 Return False
  172.         End Method
  173.        
  174.        
  175.         Method Save:Int(Overwrite:Int = False)
  176.                 Local file:TStream
  177.                 Local ft:Int = FileType(Filename)
  178.                
  179.                 If ft = 0  Or (ft = 1 And Overwrite = True) Then
  180.                         file:TStream = WriteStream(FileName)
  181.                         WriteString(file, GetIniText())
  182.                         CloseStream(file)
  183.                 Else
  184.                         Return False
  185.                 EndIf
  186.                
  187.         End Method
  188.        
  189.        
  190.         Method AddSection:TIniSection(sectionName:String)
  191.                 Return Sections.AddSection(sectionName)
  192.         End Method
  193.        
  194.        
  195.         Method GetSection:TIniSection(sectionName:String)
  196.                 Return Sections.GetSection(sectionName)
  197.         End Method
  198.        
  199.        
  200.         Method SetSectionValue(sectionName:String, key:String, value:String)
  201.                 For Local i:Int = 0 To Len(Sections._Sections) -1
  202.                         If Sections._Sections[i].name = sectionName Then
  203.                                 Sections._Sections[i].SetValue(key, value)
  204.                                 Return
  205.                         EndIf
  206.                 Next
  207.         End Method
  208.        
  209.        
  210.         Method DeleteSectionValue(sectionName:String, key:String)
  211.                 For Local i:Int = 0 To Len(Sections._Sections) -1
  212.                         If Sections._Sections[i].name = sectionName Then
  213.                                 Sections._Sections[i].DeleteValue(key)
  214.                                 Return
  215.                         EndIf
  216.                 Next
  217.         End Method
  218.        
  219.        
  220.         Method GetSectionValue:String(sectionName:String, key:String)
  221.                 For Local i:Int = 0 To Len(Sections._Sections) -1
  222.                         If Sections._Sections[i].name = sectionName Then
  223.                                 Return Sections._Sections[i].GetValue(key)
  224.                         EndIf
  225.                 Next
  226.         End Method
  227.        
  228.        
  229.         Method GetIniText:String()
  230.                 Local result:String
  231.                         For Local section:TIniSection = EachIn Sections._Sections
  232.                                  result:+section.GetSectionText()
  233.                         Next
  234.                 Return result
  235.         End Method
  236.        
  237.        
  238.         Function Create:TPertIni(filename:String)
  239.                 Local tempIni:TPertIni = New TPertIni
  240.                         tempIni.Filename = filename
  241.                         tempIni.Sections:TSectionList = TSectionList.Create()
  242.                 Return tempIni
  243.         End Function
  244. End Type
  245.  
  246.  
  247. Local ini:TPertIni = TPertIni.Create("test.ini")
  248.         'ini.AddSection("testSection")
  249.        
  250.         'ini.SetSectionValue("testSection", "testValue", "1200")
  251.         'ini.SetSectionValue("testSection", "testValue2", "1300")
  252.         'ini.SetSectionValue("testSection", "testValue3", "1500")
  253.         'ini.SetSectionValue("testSection", "testValue5=4", "1700")
  254.        
  255. ini.Load()
  256. Print ini.GetIniText()
  257. Print "value:  " + ini.getSectionValue("testSection", "testValue2")
  258. Print "value2: " + ini.getSectionValue("testSection2", "testValue2")
  259. 'ini.DeleteSectionValue("testSection", "testValue2")
  260. 'ini.Save(True)


Comments :


watusimoto(Posted 1+ years ago)

 Here's an improved version that handles comments and whitespace in the INI better...  Note that the code use is identical -- all changes made are internal and transparent to the developer.
Code: [Select]

Function SplitString:TList(inString:String, Delim:String)
Local tempList : TList = New TList
Local currentChar : String = ""
Local count : Int = 0
Local TokenStart : Int = 0

If Len(Delim)<1 Then Return Null

inString = Trim(inString)

For count = 0 Until Len(inString)
If inString[count..count+1] = delim Then
tempList.AddLast(inString[TokenStart..Count])
TokenStart = count + 1
End If
Next
tempList.AddLast(inString[TokenStart..Count])
Return tempList
End Function


Type TIniSection
Field Name:String
Field Values:TMap


Method SetValue(key:String, value:Object)
Values.Insert(Key, Value)
End Method


Method GetValue:String(Key:String)
Return String(Values.ValueForKey(Key))
End Method


Method DeleteValue(Key:String)
Values.Remove(Key)
End Method


Method GetSectionText:String()
Local result:String = "["+Name+"]~r~n"

For Local s:Object = EachIn Values.keys()
result = result + String(s) + "=" + String(Values.ValueForKey(s)) + "~r~n"
Next

Return result+"~r~n"
End Method


Function Create:TIniSection(name:String)
Local tempSection:TIniSection = New TIniSection
tempSection.name = name
tempSection.Values = New TMap
Return tempSection
End Function

End Type



Type TSectionList
Field _Sections:TIniSection[]

Method GetSection:TIniSection(sectionName:String)

For Local section:TIniSection = EachIn _Sections
If section.Name = sectionName Then Return section
Next

Return Null

End Method


Method AddSection:TIniSection(sectionName:String)
Local currentLength:Int = Len(_Sections)

_Sections = _Sections[..currentLength+1]
_Sections[currentLength] = TIniSection.Create(sectionName)

Return _Sections[currentLength]
End Method


Method RemoveSection:Int(sectionName:String)
Local currentLength:Int = Len(_Sections)

For Local i:Int = 0 To currentLength-1
If _Sections[i].Name = sectionName Then
If i < currentLength-1 Then
For Local x:Int = i To currentLength-2
_Sections[x] = _Sections[x+1]
Next
EndIf
_Sections = _Sections[..currentLength-1]

Return True

EndIf
Next

Return False
End Method


Function Create:TSectionList()
Local tempSectionList:TSectionList = New TSectionList

Return tempSectionList
End Function

End Type



Type TPertIni
Field Filename:String
Field Loaded:Int
Field Saved:Int
Field Sections:TSectionList


Method Load:Int()
Local file:TStream
Local line:String
Local tempList:TList
Local tempArray:Object[]
Local currentSection:String = ""
Local error:String


If FileType(Filename) = 1 Then

file:TStream = ReadStream(FileName)

While Not Eof(file)

line = cleanVal(ReadLine(file))


If Not (Line[..1] = ";") Then

If Line[..1] = "[" And Line[Len(Line)-1..] = "]" Then
currentSection = Line[1..Len(Line)-1]

AddSection(currentSection)
Else
If Len(currentSection) > 0 And Len(line) > 0 Then
tempArray = smartSplit(Line, "=")
If tempArray <> NULL
SetSectionValue(currentSection, String(tempArray[0]).trim(), String(tempArray[1]).trim())
EndIf
Else If Len(Line) > 0 Then
Return False 'no section header found'
EndIf
EndIf
EndIf
Wend

CloseStream(file)

EndIf

Return False
End Method


Method Save:Int(Overwrite:Int = False)
Local file:TStream
Local ft:Int = FileType(Filename)

If ft = 0  Or (ft = 1 And Overwrite = True) Then
file:TStream = WriteStream(FileName)
WriteString(file, GetIniText())
CloseStream(file)
Else
Return False
EndIf

End Method


Method AddSection:TIniSection(sectionName:String)
Return Sections.AddSection(sectionName)
End Method


Method GetSection:TIniSection(sectionName:String)
Return Sections.GetSection(sectionName)
End Method


Method SetSectionValue(sectionName:String, key:String, value:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Sections._Sections[i].SetValue(key, value)
Return
EndIf
Next
End Method


Method DeleteSectionValue(sectionName:String, key:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Sections._Sections[i].DeleteValue(key)
Return
EndIf
Next
End Method


Method GetSectionValue:String(sectionName:String, key:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Return Sections._Sections[i].GetValue(key)
EndIf
Next
End Method


Method GetIniText:String()
Local result:String
For Local section:TIniSection = EachIn Sections._Sections
result:+section.GetSectionText()
Next
Return result
End Method


Function Create:TPertIni(filename:String)
Local tempIni:TPertIni = New TPertIni
tempIni.Filename = filename
tempIni.Sections:TSectionList = TSectionList.Create()
Return tempIni
End Function
End Type





'###############################################################################
' Trim any whitespace or comments from value

function cleanVal:string(s:string)

if s then return smartSplit(s.trim(),";")[0] else return null

end function

'###############################################################################
' Split a string into substrings
' From <a href="codearcs5798.html?code=1560" target="_blank">http://www.blitzbasic.com/codearcs/codearcs.php?code=1560</a>
' by CoderLaureate, bug fix by Chris Eykamp
' This code has been declared by its author to be Public Domain code.

Function SmartSplit:String[](str:String, dels:String, text_qual:String = "~q")
Local Parms:String[] = New String[1]
Local pPtr:Int = 0
Local chPtr:Int = 0
Local delPtr:Int = 0
Local qt:Int = False
Local str2:String = ""

Repeat
Local del:String = Chr(dels[delPtr])
Local ch:String = Chr(str[chPtr])
If ch = text_qual Then
If qt = False Then
qt = True
Else
qt = False
End If
End If
If ch = del Then
If qt = True Then str2:+ ch
Else
str2:+ ch
End If
If ch = del Or chPtr = str.Length - 1 Then
If qt = False Then
Parms[pPtr] = str2.Trim()
str2 = ""
pPtr:+ 1
Parms = Parms[..pPtr + 1]
If dels.length > 1 And delPtr < dels.length Then delPtr:+ 1
End If
End If
chPtr:+ 1
If chPtr >= str.Length Then Exit
Forever
If Parms.Length > 1 Then Parms = Parms[..Parms.Length - 1]
Return Parms

End Function



Perturbatio(Posted 1+ years ago)

 nice :)I really should have implemented the loaded and saved properties...


watusimoto(Posted 1+ years ago)

 Another slight enhancement, to better handle empty values (lines like key= )
Code: [Select]
' Code for handling INI files, taken from BlitzBasic forums, by Perturbatio
' <a href="http://www.blitzmax.com/codearcs/codearcs.php?code=1890" target="_blank">http://www.blitzmax.com/codearcs/codearcs.php?code=1890</a>
' Modified by Chris Eykamp to make it more flexible
' Code in this section is public domain

' CE   Apr-2007 Better support for comments and whitespace in INI file
' CE 26-Apr-2007 Fixed problem with empty values (lines that look like key =)

Function SplitString:TList(inString:String, Delim:String)
Local tempList : TList = New TList
Local currentChar : String = ""
Local count : Int = 0
Local TokenStart : Int = 0

If Len(Delim)<1 Then Return Null

inString = Trim(inString)

For count = 0 Until Len(inString)
If inString[count..count+1] = delim Then
tempList.AddLast(inString[TokenStart..Count])
TokenStart = count + 1
End If
Next
tempList.AddLast(inString[TokenStart..Count])
Return tempList
End Function


Type TIniSection
Field Name:String
Field Values:TMap


Method SetValue(key:String, value:Object)
Values.Insert(Key, Value)
End Method


Method GetValue:String(Key:String)
Return String(Values.ValueForKey(Key))
End Method


Method DeleteValue(Key:String)
Values.Remove(Key)
End Method


Method GetSectionText:String()
Local result:String = "["+Name+"]~r~n"

For Local s:Object = EachIn Values.keys()
result = result + String(s) + "=" + String(Values.ValueForKey(s)) + "~r~n"
Next

Return result+"~r~n"
End Method


Function Create:TIniSection(name:String)
Local tempSection:TIniSection = New TIniSection
tempSection.name = name
tempSection.Values = New TMap
Return tempSection
End Function

End Type



Type TSectionList
Field _Sections:TIniSection[]

Method GetSection:TIniSection(sectionName:String)

For Local section:TIniSection = EachIn _Sections
If section.Name = sectionName Then Return section
Next

Return Null

End Method


Method AddSection:TIniSection(sectionName:String)
Local currentLength:Int = Len(_Sections)

_Sections = _Sections[..currentLength+1]
_Sections[currentLength] = TIniSection.Create(sectionName)

Return _Sections[currentLength]
End Method


Method RemoveSection:Int(sectionName:String)
Local currentLength:Int = Len(_Sections)

For Local i:Int = 0 To currentLength-1
If _Sections[i].Name = sectionName Then
If i < currentLength-1 Then
For Local x:Int = i To currentLength-2
_Sections[x] = _Sections[x+1]
Next
EndIf
_Sections = _Sections[..currentLength-1]

Return True

EndIf
Next

Return False
End Method


Function Create:TSectionList()
Local tempSectionList:TSectionList = New TSectionList

Return tempSectionList
End Function

End Type



Type TPertIni
Field Filename:String
Field Loaded:Int
Field Saved:Int
Field Sections:TSectionList


Method Load:Int()
Local file:TStream
Local line:String
Local tempList:TList
Local tempArray:Object[]
Local currentSection:String = ""
Local error:String
local v:string


If FileType(Filename) = 1 Then

file:TStream = ReadStream(FileName)

While Not Eof(file)

line = cleanVal(ReadLine(file))


If Not (Line[..1] = ";") Then ' Skip lines that are just comments

If Line[..1] = "[" And Line[Len(Line)-1..] = "]" Then
currentSection = Line[1..Len(Line)-1]

AddSection(currentSection)
Else
If Len(currentSection) > 0 And Len(line) > 0 Then
tempArray = smartSplit(Line, "=")
If tempArray <> NULL

if tempArray.length > 1 then
v = String(tempArray[1]).trim()
else
v = ""
endif

SetSectionValue(currentSection, String(tempArray[0]).trim(), v)
EndIf
Else If Len(Line) > 0 Then
Return False 'no section header found'
EndIf
EndIf
EndIf
Wend

CloseStream(file)

EndIf

Return False
End Method


Method Save:Int(Overwrite:Int = False)
Local file:TStream
Local ft:Int = FileType(Filename)

If ft = 0  Or (ft = 1 And Overwrite = True) Then
file:TStream = WriteStream(FileName)
WriteString(file, GetIniText())
CloseStream(file)
Else
Return False
EndIf

End Method


Method AddSection:TIniSection(sectionName:String)
Return Sections.AddSection(sectionName)
End Method


Method GetSection:TIniSection(sectionName:String)
Return Sections.GetSection(sectionName)
End Method


Method SetSectionValue(sectionName:String, key:String, value:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Sections._Sections[i].SetValue(key, value)
Return
EndIf
Next
End Method


Method DeleteSectionValue(sectionName:String, key:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Sections._Sections[i].DeleteValue(key)
Return
EndIf
Next
End Method


Method GetSectionValue:String(sectionName:String, key:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Return Sections._Sections[i].GetValue(key)
EndIf
Next
End Method


Method GetIniText:String()
Local result:String
For Local section:TIniSection = EachIn Sections._Sections
result:+section.GetSectionText()
Next
Return result
End Method


Function Create:TPertIni(filename:String)
Local tempIni:TPertIni = New TPertIni
tempIni.Filename = filename
tempIni.Sections:TSectionList = TSectionList.Create()
Return tempIni
End Function
End Type





'###############################################################################
' Trim any whitespace or comments from value

function cleanVal:string(s:string)

if s then return smartSplit(s.trim(),";")[0] else return null

end function

'###############################################################################
' Split a string into substrings
' From <a href="codearcs5798.html?code=1560" target="_blank">http://www.blitzbasic.com/codearcs/codearcs.php?code=1560</a>
' by CoderLaureate, bug fix by Chris Eykamp
' This code has been declared by its author to be Public Domain code.

Function SmartSplit:String[](str:String, dels:String, text_qual:String = "~q")
Local Parms:String[] = New String[1]
Local pPtr:Int = 0
Local chPtr:Int = 0
Local delPtr:Int = 0
Local qt:Int = False
Local str2:String = ""

Repeat
Local del:String = Chr(dels[delPtr])
Local ch:String = Chr(str[chPtr])
If ch = text_qual Then
If qt = False Then
qt = True
Else
qt = False
End If
End If
If ch = del Then
If qt = True Then str2:+ ch
Else
str2:+ ch
End If
If ch = del Or chPtr = str.Length - 1 Then
If qt = False Then
Parms[pPtr] = str2.Trim()
str2 = ""
pPtr:+ 1
Parms = Parms[..pPtr + 1]
If dels.length > 1 And delPtr < dels.length Then delPtr:+ 1
End If
End If
chPtr:+ 1
If chPtr >= str.Length Then Exit
Forever
If Parms.Length > 1 Then Parms = Parms[..Parms.Length - 1]
Return Parms

End Function



Crovean(Posted 1+ years ago)

 I'm quite new to BlitzMax so could you please post an example how to use this? I would like to use INI files with the applications I make... Thanks in advance :)


Guy Fawkes(Posted 1+ years ago)

 can someone plz convert to b3d?


_PJ_(Posted 1+ years ago)

 
Quote
can someone plz convert to b3d?/quote]It may need some cleaning up, and it's only the reading, but the essentials are all there:<a href="codearcs6870.html?code=2621" target="_blank">http://www.blitzbasic.com/codearcs/codearcs.php?code=2621[/url] [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal