Nubie

How to easy read KeyValues text file format?

17 posts in this topic

I have some text files with KeyValues format, example

"section1"
{
    "key1"    "value1"
    "section2"
    {
        "key2"    "value2"
    }
}

I don't know how to easy get value of sections or keys. I hope have any func can easy read it like IniRead. This format at here: https://developer.valvesoftware.com/wiki/KeyValues_class

Can't use StringInStr because it can reapeat strings, example

"rarities"
    {
        "default"
        {
            "value"     "0"
            "loc_key"       "1"         
        }
        "common"
        {
            "value"     "0"
            "loc_key"       "1"         
        }
    } 

Someone please help me. Thanks :)

 

Share this post


Link to post
Share on other sites



use

InIReadSection

It will give you the key and value, a 2 dimensional array where element[n][0] is the key and element[n][1] is the value.


Snips & Scripts


My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ

 

Share this post


Link to post
Share on other sites

Thanks! I have understand your said, example

 

Local $var = IniReadSection(@ScriptDir & "test.ini", "Section1")

For $i = 1 To $var[0][0]
MsgBox(4096, "", "Key: " & $var[$i][0] & @CRLF & "Value: " & $var[$i][1])
Next

But it's not really what I want. I want read the text file with format I said

Share this post


Link to post
Share on other sites

So, you essentially want to mirror your text file?


Snips & Scripts


My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ

 

Share this post


Link to post
Share on other sites

Nubie,

This might do the trick: ;)

#include <StringConstants.au3>
#include <Array.au3>

$sText = _
    '"rarities"' & @CRLF & _
    '    {' & @CRLF & _
    '        "default"' & @CRLF & _
    '        {' & @CRLF & _
    '            "value"     "0"' & @CRLF & _
    '            "loc_key"       "1"' & @CRLF & _
    '        }' & @CRLF & _
    '        "common"' & @CRLF & _
    '        {' & @CRLF & _
    '            "value"     "2"' & @CRLF & _
    '            "loc_key"       "3"' & @CRLF & _
    '        }' & @CRLF & _
    '    }'

; ########################################################################################

; Parse the file into an array

$aKey_Value = _ParseFile($sText)

; Extract a value
$sKey = '"rarities"\"default"\"loc_key"'

$sRet = _ReturnValue($sKey)

MsgBox($MB_SYSTEMMODAL, "Value", $sRet)

; ########################################################################################

Func _ParseFile($sText)

        Local $aKey_Value[1][2] = [[0]]

    $aArray = StringSplit($sText, @CRLF, $STR_ENTIRESPLIT)

    $sParent = ""

    For $i = 0 To $aArray[0]

        $sLine = $aArray[$i]

        StringReplace($sLine, '"', "")
        Switch @extended
            Case 0
                ; Up/down a level
                Switch StringStripWS($sLine, $STR_STRIPALL)
                    Case "{" ; Up a level
                        $sParent &= "\"
                    Case "}" ; Down a level
                        $sParent = StringRegExpReplace($sParent, "(^.*\\)(.*\\)", "$1")
                EndSwitch

            Case 2
                ; Path element
                $sParent &= StringStripWS($sLine, $STR_STRIPALL)

            Case 4
                ; Key/value pairing
                $aPairing = StringRegExp($sLine, '(?U)(".*")', 3)

                ; Increase array size
                $aKey_Value[0][0] += 1
                ReDim $aKey_Value[$aKey_Value[0][0] + 1][2]
                ; Add data
                $aKey_Value[$aKey_Value[0][0]][0] = $sParent & $aPairing[0]
                $aKey_Value[$aKey_Value[0][0]][1] = $aPairing[1]

        EndSwitch
    Next

    _ArrayDisplay($aKey_Value, "Final", Default, 8)

    Return $aKey_Value

EndFunc

Func _ReturnValue($sKey)

    $iIndex = _ArraySearch($aKey_Value, $sKey, 1)
    If Not @error Then
        Return $aKey_Value[$iIndex][1]
    Else
        Return "Error"
    EndIf
EndFunc
M23
1 person likes this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

MikahS: the text files not from me, it's from somewhere and I want easy read it

Melba23: yes, it's exactly I want, it's work very well. Thank you very much

Share this post


Link to post
Share on other sites

Nubie,

Glad I could help. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

excuse me, I have bother again.

How can list keys having in path. Example: if path is "rarities", it'll show list "default", "common" .If path is "rarities""default", it'll show list "value", "loc_key"

Share this post


Link to post
Share on other sites

Nubie,

Not too hard: ;)

#include <StringConstants.au3>
#include <Array.au3>

$sText = _
        '"rarities"' & @CRLF & _
        '    {' & @CRLF & _
        '        "default"' & @CRLF & _
        '        {' & @CRLF & _
        '            "value"     "0"' & @CRLF & _
        '            "loc_key"       "1"' & @CRLF & _
        '        }' & @CRLF & _
        '        "common"' & @CRLF & _
        '        {' & @CRLF & _
        '            "value"     "2"' & @CRLF & _
        '            "loc_key"       "3"' & @CRLF & _
        '        }' & @CRLF & _
        '    }'

; ########################################################################################

; Parse the file into an array

$aKey_Value = _ParseFile($sText)

_ArrayDisplay($aKey_Value, "Read", Default, 8)

$aMatch = _GetChildren('"rarities"', $aKey_Value)
_ArrayDisplay($aMatch, '"rarities"', Default, 8)

$aMatch = _GetChildren('"rarities"\"default"', $aKey_Value)
_ArrayDisplay($aMatch, '"rarities"\"default"', Default, 8)

; ########################################################################################

Func _GetChildren($sPath, $aKey_Value)

    ; Create array to hold children with counter
    Local $aMatch[UBound($aKey_Value)], $iCount = 0
    ; Loop through the passed array
    For $i = 1 To $aKey_Value[0][0]
        ; If the path is found in the array, extract the next item (note the need to escape the "\" character)
        $aRet = StringRegExp($aKey_Value[$i][0], "(?U)" & StringReplace($sPath, "\", "\\") & "\\(.*)(?:\\|\z)", 3)
        If Not @error Then
            ; Check if item is already in match array
            _ArraySearch($aMatch, $aRet[0])
            If @error Then
                ; and add if not
                $aMatch[$iCount] = $aRet[0]
                $iCount += 1
            EndIf
        EndIf
    Next
    ; Remove blanks from match array
    ReDim $aMatch[$iCount]

    Return $aMatch

EndFunc   ;==>_GetChildren


Func _ParseFile($sText)

    Local $aKey_Value[1][2] = [[0]]

    $aArray = StringSplit($sText, @CRLF, $STR_ENTIRESPLIT)

    $sParent = ""

    For $i = 0 To $aArray[0]

        $sLine = $aArray[$i]

        StringReplace($sLine, '"', "")
        Switch @extended
            Case 0
                ; Up/down a level
                Switch StringStripWS($sLine, $STR_STRIPALL)
                    Case "{" ; Up a level
                        $sParent &= "\"
                    Case "}" ; Down a level
                        $sParent = StringRegExpReplace($sParent, "(^.*\\)(.*\\)", "$1")
                EndSwitch

            Case 2
                ; Path element
                $sParent &= StringStripWS($sLine, $STR_STRIPALL)

            Case 4
                ; Key/value pairing
                $aPairing = StringRegExp($sLine, '(?U)(".*")', 3)

                ; Increase array size
                $aKey_Value[0][0] += 1
                ReDim $aKey_Value[$aKey_Value[0][0] + 1][2]
                ; Add data
                $aKey_Value[$aKey_Value[0][0]][0] = $sParent & $aPairing[0]
                $aKey_Value[$aKey_Value[0][0]][1] = $aPairing[1]

        EndSwitch
    Next

    Return $aKey_Value

EndFunc   ;==>_ParseFile
As always, please ask if you have any questions. :)

M23

1 person likes this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

so fast, thak you very much, it's work very well :thumbsup:

I was tried by myself but got stuck, hard to understand about Path element

Edited by Nubie

Share this post


Link to post
Share on other sites

Nubie,

Glad I could help. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
; a few changes in the Func _ParseFile($sText)
; Change 1
  ;Local $aKey_Value[1][2] = [[0]]
  Local $iArraySize = 70000 ; Manual ArraySize
  Local $aKey_Value[$iArraySize][2] = [[0]]
; Change 2
  ; Increase array size
  $aKey_Value[0][0] += 1
  ;ReDim $aKey_Value[$aKey_Value[0][0] + 1][2]

The ReDim function is taking a lot of time.. The above code works faster.

1 person likes this

Share this post


Link to post
Share on other sites
1 hour ago, pluto41 said:
; a few changes in the Func _ParseFile($sText)
; Change 1
  ;Local $aKey_Value[1][2] = [[0]]
  Local $iArraySize = 70000 ; Manual ArraySize
  Local $aKey_Value[$iArraySize][2] = [[0]]
; Change 2
  ; Increase array size
  $aKey_Value[0][0] += 1
  ;ReDim $aKey_Value[$aKey_Value[0][0] + 1][2]

The ReDim function is taking a lot of time.. The above code works faster.

woot, it's very fast, thanks very much :)

Share this post


Link to post
Share on other sites

I suggest to solve this way:

Func _ParseFile($sText)

    $aArray = StringSplit($sText, @CRLF, $STR_ENTIRESPLIT)
    Local $aKey_Value[UBound($aArray)-1][2] = [[0]]     ;declare array with max. needed size

    $sParent = ""

    For $i = 0 To $aArray[0]

        $sLine = $aArray[$i]

        StringReplace($sLine, '"', "")
        Switch @extended
            Case 0
                ; Up/down a level
                Switch StringStripWS($sLine, $STR_STRIPALL)
                    Case "{" ; Up a level
                        $sParent &= "\"
                    Case "}" ; Down a level
                        $sParent = StringRegExpReplace($sParent, "(^.*\\)(.*\\)", "$1")
                EndSwitch

            Case 2
                ; Path element
                $sParent &= StringStripWS($sLine, $STR_STRIPALL)

            Case 4
                ; Key/value pairing
                $aPairing = StringRegExp($sLine, '(?U)(".*")', 3)

                ; Increase array size
                $aKey_Value[0][0] += 1
                ; Add data
                $aKey_Value[$aKey_Value[0][0]][0] = $sParent & $aPairing[0]
                $aKey_Value[$aKey_Value[0][0]][1] = $aPairing[1]

        EndSwitch
    Next
    ReDim $aKey_Value[$aKey_Value[0][0] + 1][2] ;shortens the array to realy needed size

    Return $aKey_Value

EndFunc   ;==>_ParseFile

it's no so fast than @pluto41's solution, but faster than @Melba23's. If you have very big data (more than 70000 rows in $aKey_Value) pluto41's script crashes. As there is only one Redim used it's a little bit slower than pluto41's script. 

Share this post


Link to post
Share on other sites

Nubie,

The usual solution to reduce the number of ReDims is to resize the array as required - look for the <<<< lines:

#include <StringConstants.au3>
#include <Array.au3>

$sText = FileRead("items.txt")

; Parse the file into an array

$aKey_Value = _ParseFile($sText)

Func _ParseFile($sText)

    Local $aKey_Value[1000][2] = [[0]] ; Set a sensible start value <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    $aArray = StringSplit($sText, @CRLF, $STR_ENTIRESPLIT)

    $sParent = ""

    For $i = 0 To $aArray[0]

        $sLine = $aArray[$i]

        StringReplace($sLine, '"', "")
        Switch @extended
            Case 0
                ; Up/down a level
                Switch StringStripWS($sLine, $STR_STRIPALL)
                    Case "{" ; Up a level
                        $sParent &= "\"
                    Case "}" ; Down a level
                        $sParent = StringRegExpReplace($sParent, "(^.*\\)(.*\\)", "$1")
                EndSwitch

            Case 2
                ; Path element
                $sParent &= StringStripWS($sLine, $STR_STRIPALL)

            Case 4
                ; Key/value pairing
                $aPairing = StringRegExp($sLine, '(?U)(".*")', 3)

                ; Increase array size
                $aKey_Value[0][0] += 1
                If $aKey_Value[0][0] = UBound($aKey_Value) Then
                    ReDim $aKey_Value[UBound($aKey_Value) * 2][2] ; ReDim array if required - double current size <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                EndIf
                ; Add data
                $aKey_Value[$aKey_Value[0][0]][0] = $sParent & $aPairing[0]
                $aKey_Value[$aKey_Value[0][0]][1] = $aPairing[1]

        EndSwitch
    Next

    ReDim $aKey_Value[$aKey_Value[0][0] + 1][2] ; Resize array to remove empty elements <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    _ArrayDisplay($aKey_Value, "Final", Default, 8)

    Return $aKey_Value

EndFunc

But as I see this is game-related, my interest ends here - please read the Forum rules to make sure you keep this legal.

M23

 


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Yes I'm already know the rules, I'm sorry

Thanks all you there helped me :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now