;-- TIME_STAMP 2019-11-21 12:56:14 v 0.3 Opt('MustDeclareVars', 1) #cs Struktur Config-Datei (*.cfg) == Sektion mit Inhalt == SECTION;Key=Value;Key=;Key=Value;Key=Value... Schlüssel ohne Wert MÜSSEN mit einem "=" abgeschlossen werden! == leere Sektion == SECTION Kommentarzeilen beginnen mit "#" == Funktionen == _CfgRead() Reads a value from a key in a section _CfgWrite() Writes a value for a key in a section _CfgKeyDelete() Deletes a key in a section _CfgSectionDelete() Deletes a section _CfgKeyList() Returns all keys in a section (as array or delimited string) _CfgSectionList() Returns all sections (as array or delimited string) _CfgSectionGetArray() Returns an 2D array with all key-value-pairs of a section _CfgSectionWriteArray() Replaces (or adds) a section from a 2D array with all key-value-pairs == Hilfsfunktionen == __CfgKeyWrite __CfgSectionRead __CfgSectionWrite __CfgSectionDelete __FileWriteToLine (modified version of _FileWriteToLine) #ce ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgRead ; Description ...: Reads the value from a key in a section. ; Syntax ........: _CfgRead($_sCfg, $_sSection, $_sKey[, $_sDefault = '']) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - Section with the searched key ; $_sKey - The searched key ; $_sDefault - [optional] The default return value. Default is ''. ; Return values .: Success The value of the passed key or if not set, the default value ; Failure The default value, set @error 1 - config file does'nt exist ; The default value, set @error 2 - config file is empty ; The default value, set @error 3 - section does'nt exist ; The default value, set @error 4 - none key-value-pairs in this section ; The default value, set @error 5 - key does'nt exist in this section ; Author ........: BugFix ; =============================================================================================================================== Func _CfgRead($_sCfg, $_sSection, $_sKey, $_sDefault='') Local $aSec = __CfgSectionRead($_sCfg, $_sSection) If $aSec[0] = 0 Then Return SetError(@error,0,0) Local $aSectionLine = StringSplit($aSec[1], ';', 2) ; $STR_NOCOUNT (2) If @error Then Return SetError(4,0,0) ; none key-value-pairs in this line Local $aKeyVal, $sSectionContent = $_sSection For $i = 1 To UBound($aSectionLine) -1 $aKeyVal = StringSplit($aSectionLine[$i], '=', 2) ; $STR_NOCOUNT (2) If $aKeyVal[0] = $_sKey Then If UBound($aKeyVal) = 2 Then Return $aKeyVal[1] Else Return $_sDefault EndIf EndIf Next Return SetError(5,0,$_sDefault) EndFunc ;==>_CfgRead ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgWrite ; Description ...: Writes the value of a key in a section. ; Syntax ........: _CfgWrite($_sCfg, $_sSection, $_sKey, $_sValue) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - The section ; $_sKey - The key ; $_sValue - The value to store ; Return values .: Success 1 ; Author ........: BugFix ; =============================================================================================================================== Func _CfgWrite($_sCfg, $_sSection, $_sKey, $_sValue) Local $fH, $aSec = __CfgSectionRead($_sCfg, $_sSection) Switch @error Case 1 ; file does'nt exist Return FileWrite($_sCfg, StringFormat('%s;%s=%s\n', $_sSection, $_sKey, $_sValue)) Case 2 ; file is empty $fH = FileOpen($_sCfg, 2) ; $FO_OVERWRITE (2) FileWrite($fH, StringFormat('%s;%s=%s\n', $_sSection, $_sKey, $_sValue)) Return FileClose($fH) Case 3 ; section does'nt exist Return __CfgSectionWrite($_sCfg, StringFormat('%s;%s=%s\n', $_sSection, $_sKey, $_sValue), $aSec[0]) EndSwitch ; otherwise: section exists Local $sSectionContent = __CfgKeyWrite($_sSection, $aSec[1], $_sKey, $_sValue) Return __CfgSectionWrite($_sCfg, $sSectionContent, $aSec[0]) EndFunc ;==>_CfgWrite ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgKeyDelete ; Description ...: Deletes a key-value-pair in a section ; Syntax ........: _CfgKeyDelete($_sCfg, $_sSection, $_sKey) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - Section with the searched key ; $_sKey - The key to delete ; Return values .: Success 1 ; Failure 0, set @error 1 - config file does'nt exist ; 0, set @error 2 - config file is empty ; 0, set @error 3 - section does'nt exist ; 0, set @error 4 - none key-value-pairs in this section ; 0, set @error 5 - key does'nt exist ; Author ........: BugFix ; =============================================================================================================================== Func _CfgKeyDelete($_sCfg, $_sSection, $_sKey) Local $aSec = __CfgSectionRead($_sCfg, $_sSection) If $aSec[0] = 0 Then Return SetError(@error,0,0) Local $aSectionLine = StringSplit($aSec[1], ';', 2) ; $STR_NOCOUNT (2) If @error Then Return SetError(4,0,0) ; none key-value-pairs in this line Local $aKeyVal, $sSectionContent = $_sSection, $bDeleted = False For $i = 1 To UBound($aSectionLine) -1 $aKeyVal = StringSplit($aSectionLine[$i], '=', 2) ; $STR_NOCOUNT (2) If $aKeyVal[0] = $_sKey Then ; do nothing, will not write again $bDeleted = True Else $sSectionContent &= StringFormat(';%s=%s', $aKeyVal[0], $aKeyVal[1]) EndIf Next If Not $bDeleted Then Return SetError(5,0,0) Return __CfgSectionWrite($_sCfg, $sSectionContent, $aSec[0]) EndFunc ;==>_CfgKeyDelete ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgSectionDelete ; Description ...: Deletes a section ; Syntax ........: _CfgSectionDelete($_sCfg, $_sSection) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - The Section to delete ; Return values .: Success 1 ; Failure 0, set @error 1 - config file does'nt exist ; 0, set @error 2 - config file is empty ; 0, set @error 3 - section does'nt exist ; Author ........: BugFix ; =============================================================================================================================== Func _CfgSectionDelete($_sCfg, $_sSection) Local $aSec = __CfgSectionRead($_sCfg, $_sSection) If $aSec[0] = 0 Then Return SetError(@error,0,0) Return __CfgSectionDelete($_sCfg, $aSec[0]) EndFunc ;==>_CfgSectionDelete ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgSectionList ; Description ...: Returns a array or string of all section names ; Syntax ........: _CfgSectionList($_sCfg[, $_bRetArray=True]) ; Parameters ....: $_sCfg - Path of the config file ; $_bRetArray - [optional] Return as array or delimited string, Default is True - Array ; Return values .: Success Array with all section names, count of sections on index [0] ; Failure 0, set @error 1 - config file does'nt exist ; 0, set @error 2 - config file is empty ; Author ........: BugFix ; =============================================================================================================================== Func _CfgSectionList($_sCfg, $_bRetArray=True) If Not FileExists($_sCfg) Then Return SetError(1,0,0) Local $aSectionLine, $aKeyVal, $sRet = '' Local $aCfg = FileReadToArray($_sCfg) If @error = 2 Then Return SetError(2,0,0) ; empty file For $i = 0 To UBound($aCfg) -1 If StringLeft($aCfg[$i], 1) = '#' Then ContinueLoop ; its a comment line - skip $aSectionLine = StringSplit($aCfg[$i], ';', 2) ; $STR_NOCOUNT (2) $sRet &= $aSectionLine[0] & ';' Next $sRet = StringTrimRight($sRet, 1) Return ($_bRetArray ? StringSplit($sRet, ';') : $sRet) EndFunc ;==>_CfgSectionList ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgKeyList ; Description ...: Returns a array or string of all key names in a section ; Syntax ........: _CfgKeyList($_sCfg, $_sSection[, $_bRetArray=True]) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - Section to get the keys from ; $_bRetArray - [optional] Return as array or delimited string, Default is True - Array ; Return values .: Success 1 ; Failure 0, set @error 1 - config file does'nt exist ; 0, set @error 2 - config file is empty ; 0, set @error 3 - section does'nt exist ; 0, set @error 4 - none key-value-pairs in this section ; Author ........: BugFix ; =============================================================================================================================== Func _CfgKeyList($_sCfg, $_sSection, $_bRetArray=True) Local $sRet = '', $aRet[1] Local $aSec = __CfgSectionRead($_sCfg, $_sSection) If $aSec[0] = 0 Then Return SetError(@error,0,($_bRetArray ? $aRet : $sRet)) Local $aKeys = StringRegExp($aSec[1], "([^=;]+)=", 3) If Not IsArray($aKeys) Then Return SetError(4,0,($_bRetArray ? $aRet : $sRet)) If $_bRetArray Then Return $aKeys For $i = 0 To UBound($aKeys) -1 $sRet &= $aKeys[$i] & ';' Next Return StringTrimRight($sRet, 1) EndFunc ;==>_CfgKeyList ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgSectionGetArray ; Description ...: Returns a 2D array of all key-value-pairs in a section ; Syntax ........: _CfgSectionGetArray($_sCfg, $_sSection) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - Section to get the key-value-pairs from ; Return values .: Success 2D array: [[count_keys,section_name],[key_1,value],[key_2,value], .. [key_n,value]] ; Failure [[0,"error"]], set @error 1 - config file does'nt exist ; [[0,"error"]], set @error 2 - config file is empty ; [[0,"error"]], set @error 3 - section does'nt exist ; Author ........: BugFix ; =============================================================================================================================== Func _CfgSectionGetArray($_sCfg, $_sSection) Local $aRet[1][2] = [[0,"error"]] Local $aSec = __CfgSectionRead($_sCfg, $_sSection) If $aSec[0] = 0 Then Return SetError(@error,0,$aRet) Local $aSectionLine = StringSplit($aSec[1], ';', 2) ; $STR_NOCOUNT (2) If @error Then ; none key-value-pairs in this line $aRet[0][1] = $_sSection Return $aRet EndIf Local $aKeyVal, $iCnt = UBound($aSectionLine) ReDim $aRet[$iCnt][2] $aRet[0][0] = $iCnt -1 $aRet[0][1] = $_sSection For $i = 1 To UBound($aSectionLine) -1 $aKeyVal = StringSplit($aSectionLine[$i], '=', 2) ; $STR_NOCOUNT (2) $aRet[$i][0] = $aKeyVal[0] $aRet[$i][1] = (UBound($aKeyVal) = 2 ? $aKeyVal[1] : '') Next EndFunc ;==>_CfgSectionGetArray ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CfgSectionWriteArray ; Description ...: Writes the whole section at once from a passed 2D array with all key-value-pairs ; Syntax ........: _CfgSectionWriteArray($_sCfg, $_sSection, $_aKeyVal) ; Parameters ....: $_sCfg - Path of the config file ; $_sSection - Section to write the key-value-pairs ; $_aKeyVal - 2D array Default: [[count_keys,section_name],[key_1,val],[key_2,val],...[key_n,val]] ; or [[key_1,val],[key_2,val],...[key_n,val]] - $_1stIndex must set to "0" in this case! ; $_1stIndex - [optional] The first index with data of the passed array. Default=1, like returned from _CfgSectionGetArray() ; Return values .: Success 1 ; Failure 0, set @error 1 - $_aKeyVal is'nt a array ; 0, set @error 2 - $_aKeyVal is'nt a 2D array ; Author ........: BugFix ; =============================================================================================================================== Func _CfgSectionWriteArray($_sCfg, $_sSection, $_aKeyVal, $_1stIndex=1) Local $fH, $aSec = __CfgSectionRead($_sCfg, $_sSection) Local $iErr = @error If Not IsArray($_aKeyVal) Then Return SetError(1,0,0) If UBound($_aKeyVal, 0) <> 2 Then Return SetError(2,0,0) Local $sSectionContent = $_sSection For $i = $_1stIndex To UBound($_aKeyVal) -1 $sSectionContent &= StringFormat(';%s=%s', $_aKeyVal[$i][0], $_aKeyVal[$i][1]) Next Switch $iErr Case 0 ; section exists Return __CfgSectionWrite($_sCfg, $sSectionContent, $aSec[0]) Case 1 ; file does'nt exist Return FileWrite($_sCfg, $sSectionContent & @CRLF) Case 2 ; file is empty $fH = FileOpen($_sCfg, 2) ; $FO_OVERWRITE (2) FileWrite($fH, $sSectionContent & @CRLF) Return FileClose($fH) Case 3 ; section does'nt exist Return __CfgSectionWrite($_sCfg, $sSectionContent & @CRLF, $aSec[0]) EndSwitch EndFunc ;==>_CfgSectionWriteArray #region - Helper functions ; Builds the new section content Func __CfgKeyWrite($_sSection, $_sSectionContent, $_sKey, $_sValue) Local $aSectionLine = StringSplit($_sSectionContent, ';', 2) ; $STR_NOCOUNT (2) If @error = 1 Then ; none key-value-pairs in this line $_sSectionContent = StringFormat('%s;%s=%s', $_sSection, $_sKey, $_sValue) EndIf $_sSectionContent = $_sSection Local $aKeyVal, $bReplaced = False For $i = 1 To UBound($aSectionLine) -1 $aKeyVal = StringSplit($aSectionLine[$i], '=', 2) ; $STR_NOCOUNT (2) If $aKeyVal[0] = $_sKey Then $_sSectionContent &= StringFormat(';%s=%s', $aKeyVal[0], $_sValue) $bReplaced = True Else $_sSectionContent &= StringFormat(';%s=%s', $aKeyVal[0], $aKeyVal[1]) EndIf Next ; the key is new: If Not $bReplaced Then $_sSectionContent &= StringFormat(';%s=%s', $_sKey, $_sValue) Return $_sSectionContent EndFunc ;==>__CfgKeyWrite ; Returns an array: [line_number_in_file,line_content] Func __CfgSectionRead($_sCfg, $_sSection) Local $aRet[] = [0,''] ; if not found: line number is 0 If Not FileExists($_sCfg) Then Return SetError(1,0,$aRet) Local $aCfg = FileReadToArray($_sCfg) If @error = 2 Then Return SetError(2,0,$aRet) ; empty file Local $aMatch For $i = 0 To UBound($aCfg) -1 $aMatch = StringRegExp($aCfg[$i], "^([^;]+)", 1) If $aMatch[0] = $_sSection Then $aRet[0] = $i+1 $aRet[1] = $aCfg[$i] Return $aRet EndIf Next Return SetError(3,0,$aRet) ; section does'nt exist EndFunc ;==>__CfgSectionRead ; Writes the full section in the passed line (overwriting). Line number 0 for append. Func __CfgSectionWrite($_sCfg, $_sSectionContent, $_iSectionLine=0) If $_iSectionLine = 0 Then ; section does'nt exist Local $fH = FileOpen($_sCfg, 1) ; $FO_APPEND (1) FileWrite($fH, $_sSectionContent) Return FileClose($fH) EndIf Return __FileWriteToLine($_sCfg, $_iSectionLine, $_sSectionContent, True) EndFunc ;==>__CfgSectionWrite ; Deletes the passed line Func __CfgSectionDelete($_sCfg, $_iSectionLine) Return __FileWriteToLine($_sCfg, $_iSectionLine, '', True) EndFunc ;==>__CfgSectionDelete ; #FUNCTION# ==================================================================================================================== ; Author ........: cdkid ; Modified.......: partypooper, MrCreatoR ; BugFix: The last line needs normally also a CRLF. So here is a new parameter to define this. ; =============================================================================================================================== Func __FileWriteToLine($sFilePath, $iLine, $sText, $bOverWrite = False, $bLastLineCRLF = True) If $iLine <= 0 Then Return SetError(4, 0, 0) If Not IsString($sText) Then $sText = String($sText) If $sText = "" Then Return SetError(6, 0, 0) EndIf If $bOverWrite = Default Then $bOverWrite = False If Not (IsBool($bOverWrite) Or $bOverWrite = 0 Or $bOverWrite = 1) Then Return SetError(5, 0, 0) ; For old versions. If Not FileExists($sFilePath) Then Return SetError(2, 0, 0) Local $aArray = FileReadToArray($sFilePath) Local $iUBound = UBound($aArray) - 1 If ($iUBound + 1) < $iLine Then Return SetError(1, 0, 0) Local $hFileOpen = FileOpen($sFilePath, FileGetEncoding($sFilePath) +2) ; $FO_OVERWRITE (2) If $hFileOpen = -1 Then Return SetError(3, 0, 0) Local $sData = "" $iLine -= 1 ; Now the array is 0-based, so reduce the line number by 1. For $i = 0 To $iUBound If $i = $iLine Then If $bOverWrite Then If $sText Then $sData &= $sText & @CRLF Else $sData &= $sText & @CRLF & $aArray[$i] & @CRLF EndIf ElseIf $i < $iUBound Then $sData &= $aArray[$i] & @CRLF ElseIf $i = $iUBound Then $sData &= $aArray[$i] & ($bLastLineCRLF ? @CRLF : '') EndIf Next FileWrite($hFileOpen, $sData) FileClose($hFileOpen) Return 1 EndFunc ;==>__FileWriteToLine #endregion