Function: IniRead()

Post your working scripts, libraries and tools
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

Function: IniRead()

07 Mar 2019, 09:18

Rewritten function iniRead()

Well I've started this to reduce the nr of lines in my scripts. However I ended up with a function 75 lines long. So much for my reasoning, however this is mostly because iniRead() can be used in a flexible way. It can load all, one or a couple sections. Empty and commented lines are ignored.

If you wonder how? Because variables are local to functions, the exaption is. Referenced variables are not local to functions. So %VarRef% represents global variables in which some value is stored. %VarRef% := "ValueOfVar"

Parameters info.
InputFile:
Should be the name or full path and name to the ini file to get the variables from.

LoadSection:
When empty, all variables from the file will be loaded. Otherwise LoadSection can be a single sectionname or a couple of sectionnames, each divided by a space. The order in which there stored does not matter. LoadSection can also be a object holding the names to load.
  • String: "Section"
  • Strings: "Section3 Section2 Section5"
  • Object: ["Section3", "Section2", "Section5"]

By Megnatar.

Might be useful to others...

Code: Select all

/*
    Well I've started this to reduce the nr of lines in my scripts. However I ended up with a function 75 lines long.
    So much for my reasoning, however this is mostly because iniRead() can be used in a flexible way. It can load
    all, one or a couple sections. The order in which there stored does not matter. Empty and commented lines are ignored.
    
    If you wonder how? Because variables are local to functions, the exaption is.
    Referenced variables are not local to functions. So %VarRef% represents global variables in which some value is stored 
    
    %VarRef% := "ValueOfVar"        
    
    Parameters info.
    InputFile:          Should be the name or path to the ini file to get the variables from.
    LoadSection:        When empty, all variables from the file will be loaded. Otherwise LoadSection can be
                        a single sectionname or a couple of sectionnames, each devided by a space.
                        LoadSection can also be a object holding the names to load.
                        
                        String:     "Section"
                        Strings:    "Section3 Section2 Section5"
                        Object:     ["Section3", "Section2", "Section5"]
    
    By Megnatar.
*/

iniRead(InputFile, LoadSection = 0) {
    if (LoadSection) {
        if (IsObject(LoadSection)) {                                            ; Load multiple sections using a object
             for i, Name in LoadSection
             {
                Loop, parse, % FileOpen(InputFile, 0).read(), `n, `r
                {
                    if (InStr(A_Loopfield, Name)) {
                        SectionName := StrReplace(A_Loopfield, "["), SectionName := StrReplace(SectionName, "]")
                        Continue
                    }
                    if (SectionName) {
                        if (((InStr(A_LoopField, "[",, 1, 1)) = 1) | ((InStr(A_LoopField, "`;",, 1, 1)) = 1) | (!A_LoopField)) {
                            if (((InStr(A_LoopField, "`;",, 1, 1)) = 1) | (!A_LoopField)) {
                                Continue
                            } else {
                                SectionName := ""
                                break
                            }
                        }
                        VarRef := SubStr(A_LoopField, 1, InStr(A_LoopField, "=")-1), %VarRef% := SubStr(A_LoopField, InStr(A_LoopField, "=")+1)
                    }
                }
            }
        } else if (!IsObject(LoadSection)) {
            if ((InStr(LoadSection, " ")) > 1) {                                ; Load multiple sections using strings
                Sections := []
                Loop, Parse, LoadSection, " ", A_Space
                    Sections[A_Index] := A_Loopfield
                for i, Name in Sections
                {
                    Loop, parse, % FileOpen(InputFile, 0).read(), `n, `r
                    {
                        if (InStr(A_Loopfield, Name)) {
                            SectionName := StrReplace(A_Loopfield, "["), SectionName := StrReplace(SectionName, "]")
                            Continue
                        }
                        if (SectionName) {
                            if (((InStr(A_LoopField, "[",, 1, 1)) = 1) | ((InStr(A_LoopField, "`;",, 1, 1)) = 1) | (!A_LoopField)) {
                                if (((InStr(A_LoopField, "`;",, 1, 1)) = 1) | (!A_LoopField)) {
                                    Continue
                                } else {
                                    SectionName := ""
                                    break
                                }
                            }
                            VarRef := SubStr(A_LoopField, 1, InStr(A_LoopField, "=")-1), %VarRef% := SubStr(A_LoopField, InStr(A_LoopField, "=")+1)
                        }
                    }
                }
            } Else {                                                        ; Load single section
                Loop, parse, % FileOpen(InputFile, 0).read(), `n, `r
                {
                    if (InStr(A_Loopfield, LoadSection)) {
                        SectionName := StrReplace(A_Loopfield, "["), SectionName := StrReplace(SectionName, "]")
                        Continue
                    }
                    If (SectionName) {
                        if ((InStr(A_LoopField, "[",, 1, 1)) = 1)
                            Break
                        VarRef := SubStr(A_LoopField, 1, InStr(A_LoopField, "=")-1), %VarRef% := SubStr(A_LoopField, InStr(A_LoopField, "=")+1)        
                    }
                }
            }
        }
    } else if (!LoadSection) {                                              ; Load all variables from ini
        Loop, parse, % FileOpen(InputFile, 0).read(), `n, `r
        {
            if (((InStr(A_LoopField, "[",, 1, 1)) = 1) | ((InStr(A_LoopField, "`;",, 1, 1)) = 1) | (!A_LoopField))
                Continue
            VarRef := SubStr(A_LoopField, 1, InStr(A_LoopField, "=")-1), %VarRef% := SubStr(A_LoopField, InStr(A_LoopField, "=")+1)
        }
    }
    Return
}
Last edited by megnatar on 26 Mar 2020, 18:30, edited 12 times in total.
swagfag
Posts: 3973
Joined: 11 Jan 2017, 17:59

Re: Function: IniRead()

07 Mar 2019, 10:02

ignoring the fact that dumping vars into the global(or whatever scope, for that matter) scope probably isnt the way to go about this, how are these variables ure creating made accessible outside the function?
or are u suggesting people write their scripts inside the function, after the loop?
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

Re: Function: IniRead()

07 Mar 2019, 10:54

because of the variable reference - %TempVar% - that is used in the loop.

And because of this:
Functions Local
•A dynamic variable reference may resolve to an existing global variable if no local variable exists by that name.

Here test it!

Code: Select all

/* 
[ScriptGui]
; comment should be here
SomeObject=MyObj[]
Gui_X=387
Gui_Y=144
Gui_W=160
Gui_H=28
[ScriptVars]
Tabnr=1
ClientApp=Q:\FileIsHere\ThisFile.exe
Folder=Q:\Some\Path\To\Here

*/
#NoEnv

ReadIni(A_ScriptFullPath)
MsgBox % ""
. "Gui_X = " Gui_X "`n"
. "Gui_Y = " Gui_Y "`n"
. "Gui_W = " Gui_W "`n"
. "Gui_H = " Gui_H "`n"
. "Tabnr = " Tabnr "`n"
. "ClientApp = " ClientApp "`n"
. "Folder = " Folder "`n"
. "SomeObject = " SomeObject "`n"
ExitApp

ReadIni(InputFile) {
    local TmpVar                                                   

    Loop, parse, % FileOpen(InputFile, 0).read(), `n, `r "/*"
    {
        if (((InStr(A_LoopField, "[")) = 1 ? 1) || ((InStr(A_LoopField, "`;")) = 1 ? 1) || !A_LoopField)
            Continue
        If (A_Index = 13)
            Break
            
        TmpVar := SubStr(A_LoopField, 1, InStr(A_LoopField, "=")-1)
        %TmpVar% := SubStr(A_LoopField, InStr(A_LoopField, "=")+1) 
    }                                                              
}
Last edited by megnatar on 07 Mar 2019, 13:13, edited 3 times in total.
just me
Posts: 7227
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Function: IniRead()

07 Mar 2019, 11:15

INI-files are usually divided into sections for a reason.

What will your function do with

Code: Select all

[Edit1]
X=10
Y=10
W=100
H=20
[ListView1]
X=10
Y=40
W=300
H=100
?

And what happens with comment lines?
swagfag
Posts: 3973
Joined: 11 Jan 2017, 17:59

Re: Function: IniRead()

07 Mar 2019, 11:19

A dynamic variable reference may resolve to an existing global variable if no local variable exists by that name.
everyday we stray further from god's light
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

Re: Function: IniRead()

07 Mar 2019, 12:14

just me wrote:
07 Mar 2019, 11:15
INI-files are usually divided into sections for a reason.

What will your function do with

Code: Select all

[Edit1]
X=10
Y=10
W=100
H=20
[ListView1]
X=10
Y=40
W=300
H=100
?

And what happens with comment lines?
Yeah it's true, the function can only be successful when the file is read from path. I could filter that though, let it read the contant from var.
Sections will be ignored, it imports the whole ini. Sections wont exist as variables..

Comments?
Good point. They will probably be stored as part of, or as a variable depending on where the comment is placed.
I will fix that!
toralf
Posts: 792
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Function: IniRead()

07 Mar 2019, 12:33

You are checking for a section by looking for a [. But the [ could be the value of a var. it would be better if you check if [ is the first character of that line. And maybe also check if there is a closing ].
ciao
toralf
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

Re: Function: IniRead()

07 Mar 2019, 13:14

toralf wrote:
07 Mar 2019, 12:33
You are checking for a section by looking for a [. But the [ could be the value of a var. it would be better if you check if [ is the first character of that line. And maybe also check if there is a closing ].
Fixed!
Thanx for the good comment!
You have any more "what if's" available?
just me
Posts: 7227
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Function: IniRead()

07 Mar 2019, 13:22

If you look a bit closer at my example you see that the keys X, Y, W, and H will be read twice with partially different values. AFAICS, only the second value will be available after the function call.
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

Re: Function: IniRead()

19 Mar 2019, 12:30

just me wrote:
07 Mar 2019, 13:22
If you look a bit closer at my example you see that the keys X, Y, W, and H will be read twice with partially different values. AFAICS, only the second value will be available after the function call.

Yes i see that local variables are currently not supported. Although, the only situation I can think of when only loading one section. Is when a other function ore class uses IniRead. I don't know about others but I rarely read ini's from there. But for the sake of compatibility I will make it so that a array is returned by IniRead when loading a single section. When I have time.....
nou
Posts: 26
Joined: 24 Feb 2019, 21:21

Re: Function: IniRead()

20 Mar 2019, 13:22

What about this code? Run it, and then call the variables by doing: section.key

note: For some reason, when I make an associative array in the function using

Code: Select all

%sectionList%[key] := value
I'm able to find the variable outside the function. So if my ini file was like:

Code: Select all

[Edit1]
X=10 ; comments on side? 
Y=10
W=100
H=20	; randomly random comments. 
[ListView1]
X=10
Y=40
; more pseudo comments? 
W=300
H=100




M = 34





L= 85
I can find the value OUTSIDE the function by just doing this:

Code: Select all

iniRead("test.ini")
MsgBox % Listview1.W
Here's the code to the function I use

Code: Select all

; Function here: 
IniRead(filename)
{
; ************************* Read File *************************

	iniFile := FileOpen(filename, "r")
	ini := iniFile.read()
	ini.close()

; ********************* String Replace ************************

	; gives every comment it's own new line
	ini := StrReplace(ini, ";", "`r`n;")

	; removes all lines that starts with ; 
	ini := RegExReplace(ini, ";.*")

	; replaces all (`r`n) with (`n)
	ini := StrReplace(ini, "`r`n", "`n")

	; removes all doublespacings
	outCount := 1
	While (outCount != 0)
		ini := StrReplace(ini, "`n`n", "`n", OutCount)

; *************************************************************

	; splits by the `n
	arrayIni := StrSplit(ini, "`n")

	; makes an array to keep track of our Sections
	SectionList := []

; ********************* Getting the Info **********************

	; enumerate array + variables
	for key, value in arrayIni
		{
			; Regex search for starting "[" and ending "]"
			RegExMatch(trim(value), "^\[.*?]$", checkSection)
			if (trim(value) = checkSection)
			{
				; remove the first and last characters, the brackets. 
				section := substr(checkSection, 2, -1)

				; adds this into our list of Sections
				SectionList.push(section)

				; if found, create a new array with that as an array name. 
				%section% := {}
			}
			else 
				{
					; splits the line by the "=" sign. 
					newKey := StrSplit(value, "=")

					; stores the left + right values into our array, respectively.
					%section%[TRIM(newKey.1)] := TRIM(newKey.2)
				}

		}
; *************************************************************

	;~ ; check our arrays
	;~ 		str := ""

	;~ ; check our array
	;~ 	for index, Section in SectionList
	;~ 	{
	;~ 		; checks the name of the section
	;~ 		str .= Index ": " Section "`n"

	;~ 		; checks each section's key + value
	;~ 		for key, value in %Section%
	;~ 			str .= key ": " value "`n"

	;~ 		str .= "`n"
	;~ 	}

	;~ 	MsgBox % str

	return SectionList
}
Last edited by nou on 13 Jun 2019, 01:18, edited 1 time in total.
lblb
Posts: 150
Joined: 30 Sep 2013, 11:31

Re: Function: IniRead()

21 Mar 2019, 01:25

Reminds me of the conceptually similar globalsFromIni() from the old forum that creates global variables:

https://autohotkey.com/board/topic/25515-globalsfromini-creates-globals-from-an-ini-file/
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

Re: Function: IniRead()

22 Mar 2019, 10:35

nou wrote:
20 Mar 2019, 13:22
What about this code? Run it, and then call the variables by doing: section.key

note: For some reason, when I make an associative array in the function using

Code: Select all

%sectionList%[key] := value
I'm able to find the variable outside the function. So
............
That's a good idea, to reference the section as 'attached variable'. why didn't I think of that. Honestly I was not to fond of the idea of returning a array. After all, the whole idea was to quickly load some variables from a ini. I will change it in due time...
nou
Posts: 26
Joined: 24 Feb 2019, 21:21

Re: Function: IniRead()

22 Mar 2019, 11:58

XD Don't think of it as "returning it as an array". think of it as a "Section.key" variable, as oppose to a "sectionkey" variable. You know, a variable with an extra period in between. Otherwise, without any separator between the section and key, you might run into issues when you do something like this:

Code: Select all

[Setting]
s1=25

[Settings]
1=3
freakkk
Posts: 25
Joined: 21 Sep 2014, 20:14

Re: Function: IniRead()

26 Mar 2019, 01:46

Here is a simple ini file class I used to use before I started to upgrade my data storage to json:

Code: Select all

  ;-- read values of ini file into obj
  oIni := new IniFileObj( A_ScriptDir "\MyIniFile1.ini" )

  ;-- If file doesn't exist, create sections and add keys to it
  If !FileExist( A_ScriptDir "\MyIniFile1.ini" ){
    oIni.section1 := {}
    oIni.section1.key1 := "section 1, key 1"
    oIni.section1.key2 := "section 1, key 2"
    oIni.section2 := {}
    oIni.section2.key1 := "section 2, key 1"
    oIni.section2.key2 := "section 2, key 2"
    oIni.Save()    ; save to file
  }

  ; MsgBox, % oIni.section1.key1
  MsgBox, % Obj2String( oIni )   ;- display all values

  ;-- Create ini file obj, set to save settings on exit
  oIni := new IniFileObj( A_ScriptDir "\MyIniFile2.ini", true )
  If !FileExist(A_ScriptDir "\MyIniFile2.ini")
    oIni.section3 := { key1: "this is section three, key one.." }

ExitApp


class IniFileObj {
  __New( filePath, saveOnExit:=false ){
    this.filePath := filePath
    while thisLine := StrSplit( FileOpen(filePath,"r").Read(), "`n", "`r" )[ A_Index ]
      If RegExMatch(thisLine,"((\[(?<Section>.*)\])|(?<Key>\w+)=(?<Value>.*)$)",_)
        _Key ? this[thisSection].Insert(_key,_value) : "", _Section ? (thisSection:=_Section, this[thisSection]:=[] )
    saveOnExit ? OnExit( ObjBindMethod(this, "Save") )      
  }
  Save(){
    For section, objSectionKeys in this
      For key, value in objSectionKeys
        IniWrite, % value, % this.filePath, % section, % key
  }
}

Obj2String(o,ind="",indChar="     ")  {
  For i, v in o
    l .= (l ? "`r`n" : "") ind i " - " v, l .= IsObject(v) ? "`r`n" %A_ThisFunc%(v, ind indChar, indChar) : ""
  return l
}
toralf
Posts: 792
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Function: IniRead()

26 May 2019, 15:04

Dear freakkk,

Thanks for posting the class.

If I understand correctly the class can’t have a section called filepath, is that correct?

Do you also have a Version that supports default values? E.g. by providing an default {section:{key:value}} object for the __New() method.

Is the a reason you use iniwrite on save() instead of filewrite or fileappend?
ciao
toralf
toralf
Posts: 792
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Function: IniRead()

26 May 2019, 15:43

Three more questions
Does the while loop read the file completely each iteration? That seams to be an overdose of doing almost everything on one line
You regex does not handle comments in the ini, is that correct?
And the while loop will stop on empty lines...

I do not want to criticize you. I appreciate what you have created and that you share it. I consider to use it myself. But before I want to understand it’s limits or get into a discussion on how these could be overcome.
ciao
toralf
toralf
Posts: 792
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Function: IniRead()

27 May 2019, 06:46

Hi there,

This would be my mod of the class.
Basically, I extended it with handling default values, changed the While to a For Loop and modified the RegEx to handle comments correctly. Thus, I hope it is more robust against human interaction with the ini file.

Code: Select all

  IniFileName := A_ScriptDir "\MyIniFile1.ini"
  If !FileExist( IniFileName ){
    Content = 
(
[Section1]
Key1=Section 1, Key 1
Key2=Section 1, Key 2
;comment with [Section Name]
;[Commented Section]
  ;  comment with [Commented Section Name]
  ;  [Commented Section indented]
   [Section2]
Key1=Section 2, Key 1
Key2=Section 2, Key 2
Key3=Text with = as a test
;Key4=a comment
  ;  Key5=a comment indented
  ;  comment = with equal sign
Key6 =  Spaces around =
  Key7=Key indented
)
  FileAppend, %Content%, %IniFileName%
  }

  DefaultValues := {Section1:{Key2: "Value exists in INI"
                            , Key4: "Value from Default"}
                 , "Section_test":{Key1: A_ScriptDir
                                 , 4: A_USerName }}

  oIni := new IniFileObj( IniFileName, DefaultValues )
  MsgBox, % Obj2String( oIni )   ;- display all values

  oIni := new IniFileObj( A_ScriptDir "\MyIniFile2.ini", ,true )
  If !FileExist(A_ScriptDir "\MyIniFile2.ini")
    oIni.section3 := { key1: "this is section three, key one.." }
  MsgBox, % Obj2String( oIni )   ;- display all values
  ExitApp
  
class IniFileObj {
  __New( filePath, DefaultValues := "", saveOnExit:=false ){
    For Section, KeysAndValues in DefaultValues {
      this[Section]:=[]
      For key, value in KeysAndValues
        this[Section].Insert(key,value)
    }
    this.filePath := filePath
    For i, thisLine in StrSplit( FileOpen(filePath,"r").Read(), "`n", "`r" ) 
      If RegExMatch(thisLine,"^\s*(?<!;)((\[(?<Section>.*?)\])|(?<Key>\w+)\s*=(?<Value>.*)$)",_)
        _Key ? this[thisSection].Insert(_key,_value) : "", _Section ? (thisSection:=_Section, !this.Haskey(thisSection) ? this[thisSection]:=[]) 
    saveOnExit ? OnExit( ObjBindMethod(this, "Save") ) 
  }
  Save(){
    For Section, KeysAndValues in this
      For key, value in KeysAndValues
        IniWrite, % value, % this.filePath, % Section, % key
  }
}

Obj2String(o,ind="",indChar="     ")  {
  For i, v in o
    l .= (l ? "`r`n" : "") ind i " - " v, l .= IsObject(v) ? "`r`n" %A_ThisFunc%(v, ind indChar, indChar) : ""
  return l
}
ciao
toralf
Adventurer
Posts: 5
Joined: 18 Apr 2019, 06:24

Re: Function: IniRead()

17 Jul 2019, 17:42

toralf wrote:
27 May 2019, 06:46
Hi there,

This would be my mod of the class.
Basically, I extended it with handling default values, changed the While to a For Loop and modified the RegEx to handle comments correctly. Thus, I hope it is more robust against human interaction with the ini file.

Code: Select all

  IniFileName := A_ScriptDir "\MyIniFile1.ini"
  If !FileExist( IniFileName ){
    Content = 
(
[Section1]
Key1=Section 1, Key 1
Key2=Section 1, Key 2
;comment with [Section Name]
;[Commented Section]
  ;  comment with [Commented Section Name]
  ;  [Commented Section indented]
   [Section2]
Key1=Section 2, Key 1
Key2=Section 2, Key 2
Key3=Text with = as a test
;Key4=a comment
  ;  Key5=a comment indented
  ;  comment = with equal sign
Key6 =  Spaces around =
  Key7=Key indented
)
  FileAppend, %Content%, %IniFileName%
  }

  DefaultValues := {Section1:{Key2: "Value exists in INI"
                            , Key4: "Value from Default"}
                 , "Section_test":{Key1: A_ScriptDir
                                 , 4: A_USerName }}

  oIni := new IniFileObj( IniFileName, DefaultValues )
  MsgBox, % Obj2String( oIni )   ;- display all values

  oIni := new IniFileObj( A_ScriptDir "\MyIniFile2.ini", ,true )
  If !FileExist(A_ScriptDir "\MyIniFile2.ini")
    oIni.section3 := { key1: "this is section three, key one.." }
  MsgBox, % Obj2String( oIni )   ;- display all values
  ExitApp
  
class IniFileObj {
  __New( filePath, DefaultValues := "", saveOnExit:=false ){
    For Section, KeysAndValues in DefaultValues {
      this[Section]:=[]
      For key, value in KeysAndValues
        this[Section].Insert(key,value)
    }
    this.filePath := filePath
    For i, thisLine in StrSplit( FileOpen(filePath,"r").Read(), "`n", "`r" ) 
      If RegExMatch(thisLine,"^\s*(?<!;)((\[(?<Section>.*?)\])|(?<Key>\w+)\s*=(?<Value>.*)$)",_)
        _Key ? this[thisSection].Insert(_key,_value) : "", _Section ? (thisSection:=_Section, !this.Haskey(thisSection) ? this[thisSection]:=[]) 
    saveOnExit ? OnExit( ObjBindMethod(this, "Save") ) 
  }
  Save(){
    For Section, KeysAndValues in this
      For key, value in KeysAndValues
        IniWrite, % value, % this.filePath, % Section, % key
  }
}

Obj2String(o,ind="",indChar="     ")  {
  For i, v in o
    l .= (l ? "`r`n" : "") ind i " - " v, l .= IsObject(v) ? "`r`n" %A_ThisFunc%(v, ind indChar, indChar) : ""
  return l
}
Spaces in the key name break it, e.g. 'key1' works but 'key 1' doesn't.

Cap'n Odin on Discord showed me how to fix this.

Code: Select all

;Code to replace:
If RegExMatch(thisLine,"^\s*(?<!;)((\[(?<Section>.*?)\])|(?<Key>\w+)\s*=(?<Value>.*)$)",_)

;Option #1 - This allows letters, numbers, and spaces to match:
If RegExMatch(thisLine,"^\s*(?<!;)((\[(?<Section>.*?)\])|(?<Key>(\w| )+?)\s*=(?<Value>.*)$)",_)

;Option #2 - This allows anything that isn't the equal sign to match:
If RegExMatch(thisLine,"^\s*(?<!;)((\[(?<Section>.*?)\])|(?<Key>.+?)\s*=(?<Value>.*)$)",_)
freakkk
Posts: 25
Joined: 21 Sep 2014, 20:14

Re: Function: IniRead()

29 Dec 2019, 15:55

toralf wrote:
26 May 2019, 15:04
Dear freakkk,
Well first of all, toralf it's wonderful to see your name still active on the forum! I've learned a lot and become inspired by a number of things that you have posted before in the past, so I feel honored that you were taking a look at my code. Somehow I never saw the notification that you responded to my post until now.

toralf wrote:
27 May 2019, 06:46
This would be my mod of the class.
I'm glad you were able to modify it to fit your needs. I'll most likely replace my version with your modified version, but I honestly barely use ini files anymore (see also JsonFile).
toralf wrote:
26 May 2019, 15:04
Do you also have a Version that supports default values? E.g. by providing an default {section:{key:value}} object for the __New() method.
That is a very good point. I created that library many years ago, and haven't looked at it since. I've gotten much better at writing classes since then, and looking back realize how incomplete this was.
toralf wrote:
26 May 2019, 15:04
Is the a reason you use iniwrite on save() instead of filewrite or fileappend?
If I were recreating this library now, I would definately be doing a single filewrite rather than that approach!
toralf wrote:
26 May 2019, 15:43
You regex does not handle comments in the ini, is that correct?
I've never actually used (or seen.??) comments in ini files, so I never thought to handle that. I'm glad your mod handles comments!

Apologies for not responding back to you sooner toralf!

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Google [Bot] and 24 guests