Jump to content

[Solved] Reading variables from a text file


gsbaker
 Share

Recommended Posts

I am new to the forums (today) and also new to AutoIT, but learning quickly :) . I am wondering what options are available for reading variables from a text file? What I have learned so far is:

Option 1 - INI files

- store variables as values in an INI file and use IniRead and IniWrite to read them into AutoIT variables / write updated values back to the INI file.

Option 2 - Other TXT files

- store variable declaration statements (e.g. $var = "xxxx") in a text file and use "#include" to include the text file in AutoIT. Use FileOpen and FileWriteLine to re-create the text file with updated variable values.

Option 3 - Use Windows Registry

- read/store variables in Windows Registry with RegRead and RegWrite. Not my preferred alternative - not sure why, other than my perception that messing with the Registry is not a good idea, and storing variables here makes them hard for users to find.

So far I have been using Option 2 which works great until I try and compile the AutoIT code - which includes the current variables in the compiled code and does not allow for subsequent updates to those variables.

My questions are:

1. Are there other options (such as Option 2 with FileRead which I couldn't seem to get to work)?

2. If option 1 (or some other option) is the best alternative, what is the best way to accommodate multi-dimensional arrays (e.g. $sArray[280][3] = [["link1", "name1", 1],["link2", "name2", 5],["link3", "name3", 0],[etc...]]) in an INI file?

Thanks for your help.

Edited by gsbaker
Link to comment
Share on other sites

  • Moderators

gsbaker,

Welcome to the Autoit forum. :)

Like you I am none to keen on fiddling with the registry so I tend to use ini files to store variables - AutoIt's Ini* commands make it so easy to use them I am prepared to accept the "dinosaur" label from the younger rapscallions here. ;)

As to storing multidimensional arrays, the best way I have found is to save them to a specific file with _FileWriteFromArray after running them through a short concatenation function in which you create a temporary array where each line consists of the [0], [1], [2] elements of the original array with a suitable delimiter. In your case the resulting array would look like this:

[0]  link1,name1,1
[1]  link2,name2,5
[2]  link3,name3,0

and once saved the file would look like this:

link1,name1,1
link2,name2,5
link3,name3,0

You can then read the file into your script using _FileReadToArray and run a loop with StringSplit to get each line into separate elements before inserting them into the multi-dimensional array.

I hope that makes sense - please ask if not. :idiot:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

There are plenty of ways to store individual variables. Ini files have my preference. I'd stay away from using #include for variables that are supposed to be changed often.

1D arrays can be saved with _FileWriteFromArray, like M23 suggested.

For 2D arrays you could use Excel, or SQLite. Excel has the advantage that variables are easily updated manually, but all users must have excel installed, SQlite will work on any PC, but you might need to write a way to update the file.

For multi dimensional arrays I wrote (That reminds me I never finished the XML version, or the version that supports datatypes)

The disadvantage is that, while you can save the string as a plain textfile, it's not always clear what variable is which, making manual updates possible, but often confusing.

The advantage is that you just use two functions out of the box, instead of having to find a reliable way to make your arrays 1D.

Link to comment
Share on other sites

Thanks for the replies. Somehow now I feel a bit like I'm drinking from a firehose :)

@M23 - could I accomplish the same by storing values to the variables.ini file along the lines of:

- item1 = "link1,name1,1"

- item2 = "link2,name2,5"

- item3 = "link3,name3,0"

Presumably I could then IniRead each value and somehow parse the individual elements into the multi-dimensional array? Something like:

For $n = 1 to $numItems (which in my case may be fixed at 280)

     $item = IniRead("variables.ini", "section", "item" & $n, "")
     $itemArray = StringSplit($item, ",")

     $sArray[$n][0] = $itemArray[1]
     $sArray[$n][1] = $itemArray[2]
     $sArray[$n][2] = $itemArray[3]

Next

In this way I would not need a separate file for the multi-dimensional array values, but could store all variable values in the ini file.

Incidentally, are comments allowed in ini files - to provide commentary on the variables and their usage?

@Tvern - I'm providing a GUI interface for the users to maintain the variable values, so they really should not need to edit the variable text file (using Excel or SQLite). And if comments are allowed in the .ini files (as per my question above) then I could provide explanatory comments directly in the file.

Thanks again folks.

Link to comment
Share on other sites

  • Moderators

gsbaker,

You certainly could do as you suggest, but I would not include the "" in the data - just another thing to parse and discard.

And take a look at IniReadSection - you can get all the data into an array in one easy call to make your life easier. ;)

As to comments in ini files - the standard MS ini file format does not include comments, but here is a pretty comprehensive summary of what you can and cannot do. Just adapt it to your needs.

Good luck - you know where we are if you run into any difficulties. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

Use this code

#Include <Array.au3>

Dim $myArray[2][10]
$myArray[0][0] = "0|0"
$myArray[0][1] = "0|1"
$myArray[0][2] = "0|2"
$myArray[0][3] = "0|3"
$myArray[0][4] = "0|4"
$myArray[0][5] = "0|5"
$myArray[0][6] = "0|6"
$myArray[0][7] = "0|7"
$myArray[0][8] = "0|8"
$myArray[0][9] = "0|9"

$myArray[1][0] = "1|0"
$myArray[1][1] = "1|1"
$myArray[1][2] = "1|2"
$myArray[1][3] = "1|3"
$myArray[1][4] = "1|4"
$myArray[1][5] = "1|5"
$myArray[1][6] = "1|6"
$myArray[1][7] = "1|7"
$myArray[1][8] = "1|8"
$myArray[1][9] = "1|9"

_ArrayDisplay($myArray,"Save myArray")
SaveArrayToSection("ArrayFile.ini","NewSectionName",$myArray)
$myArray = GetArrayFromSection("ArrayFile.ini","NewSectionName")
_ArrayDisplay($myArray,"Get myArray")

Dim $imyArray[10]
$imyArray[0] = "0"
$imyArray[1] = "1"
$imyArray[2] = "2"
$imyArray[3] = "3"
$imyArray[4] = "4"
$imyArray[5] = "5"
$imyArray[6] = "6"
$imyArray[7] = "7"
$imyArray[8] = "8"
$imyArray[9] = "9"

_ArrayDisplay($imyArray,"Save imyArray")
SaveArrayToSection("ArrayFile.ini","iNewSectionName",$imyArray)
$myArray = GetArrayFromSection("ArrayFile.ini","iNewSectionName")
_ArrayDisplay($myArray,"Get myArray")



Func GetArrayFromSection($FileName,$NewSectionName)
Local $SectionData = "" , $myArray[1]
$SectionData = IniReadSection($FileName,$NewSectionName)
if @error Then Return SetError(1,0,0)
Select
Case Not StringInStr($SectionData[1][0],"|")
For $i = 1 To $SectionData[0][0]
$rows = $SectionData[$i][0]
ReDim $myArray[$rows + 1]
$myArray[$rows] = BinaryToString($SectionData[$i][1])
Next
Case Else
Local $icols = 0
For $i = 1 To $SectionData[0][0]
$Elements = $SectionData[$i][0]
$SpArray = StringSplit($Elements,"|")
$rows = $SpArray[1]
$cols = $SpArray[2]
if $cols > $icols Then $icols = $cols
ReDim $myArray[$rows + 1][$icols + 1]
$myArray[$rows][$cols] = BinaryToString($SectionData[$i][1])
Next
EndSelect
Return SetError(0,0,$myArray)
EndFunc


Func SaveArrayToSection($FileName,$NewSectionName,$myArray)
if Not IsArray($myArray) Then Return SetError(1,0,0)
Local $SectionData = ""
Switch UBound($myArray,0)
Case 1
For $i = 0 To UBound($myArray) - 1
$SectionData &= $i & "=" & StringToBinary($myArray[$i]) & @LF
Next
Case 2
For $i = 0 To UBound($myArray) - 1
For $j = 0 To UBound($myArray,2) - 1
$SectionData &= $i & "|" & $j & "=" & StringToBinary($myArray[$i][$j]) & @LF
Next
Next
EndSwitch
Return IniWriteSection($FileName,$NewSectionName,$SectionData)
EndFunc

صرح السماء كان هنا

 

Link to comment
Share on other sites

Thanks folks. I am getting there.

On to another (related) challenge. For the variables that are NOT arrays, is there a way to:

a. use IniReadSection to create an array of Keys and Values

b. Use the "Key" as the variable name and assign it the "Value" for that key along the lines of:

$variables = IniReadSection("variables.ini", "section")
For $n=1 to $variables[0][0]
     $key1 = $value1
Next

Where $key1 is the Key value contained in $variables[$n][0] and $value1 is the value contained in $variables[$n][1]?

I've tried the statement:

$ & $variables[$n][0] = $variables[$n][1]

hoping it would pre-pend the '$' to the value in $variables[$n][0] but that didn't work.

I've also tried having the '$' part of the Key value in the .ini file and using the statement:

String($variables[$n][0]) = $variables[$n][1]

but that didn't work either.

Each of the Keys are unique and represent what I would ultimately like to use as the variable name. I could just use a bunch of IniRead statements and process each one individually. I was just wondering if there is a way to do it with IniReadSection.

Thanks for any help.

Link to comment
Share on other sites

Why do you need to reassign the array elements to variables? You can directly access them using the array elements without having to resort to a hack like Assign.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Well, my code is likely not the most elegant, but here is where I am. Also, I should point out that this is not original code of mine - I am updating code (with permission) originally developed by someone else (originally about 8,600 lines of code). The complete AutoIT code set, in a nutshell does the following:

  • Read prior variable values
  • Presents a GUI and enables user to update/change variable settings
  • Saves updated variables
  • Uses those variables in a relatively complex set of iterations with a Commercial application to generate a host of static html files using "Export to HTML" functionality within the commercial application (basically xml and xslt I think).

The "variables" file consists of:

  • 72 - "single" variables
  • 1 - array of 20 variables, each with 3 elements "linkname", "title", and "number of items"
  • 1 - array of 280 variables, each with 3 elements (same as above)

Items 2 and 4 have been programmed using a set of variable names (for each of the 372 variables identified above). I'm not really sure why there are 2 separate arrays that are so similar, but the existing coding uses a different variable naming structure for each of the 2. I was trying to keep everything simple (at least for round 1) and not get into re-naming each of the variables (which I think create a bit of a nightmare in Step 4 code - although "Replace All" might work well :) ).

I started out using a simple text file to capture the 372 variables and "#include" the file, but found that didn't work too well when I compiled the code :idiot: . Hence my migration to .ini files ;)

So far I have completed the coding necessary for item 1 (using .ini files), and it is working with Item 2 (i.e. it presents those variables in the GUI). That code segment is as follows:

; Read previous variable values from .ini file
; 1. Read single variables from ini File
Local $variablesArray[72][2]

$variablesArray = IniReadSection("MLMJ gsb Skin v1 Properties.ini","variables")
   For $n = 1 to $variablesArray[0][0]
     Assign ($variablesArray[$n][0],$variablesArray[$n][1], 2)
   Next
    
; 2. Read Genre array variables
Global $genreArray[20][3]
Global $Glink = 0, $Gtitle=1, $GnumMovies=2
Local $SectionData = "" 

$SectionData = IniReadSection("MLMJ gsb Skin v1 Properties.ini","genreArray")
   For $n = 0 to $SectionData[0][0]-1
     $itemArray = StringSplit($SectionData[$n+1][1],"|")
     $genreArray[$n][$Glink] = $itemArray[1]
     $genreArray[$n][$Gtitle] = $itemArray[2]
     $genreArray[$n][$GnumMovies] = $itemArray[3]
   Next

; 3. Read Series array variables
Global $seriesArray[280][3]
Global $Slink=0, $Stitle=1, $SnumMovies=2
Local $SectionData = "" 

$SectionData = IniReadSection("MLMJ gsb Skin v1 Properties.ini","seriesArray")
   For $n = 0 to $SectionData[0][0]-1
     $itemArray = StringSplit($SectionData[$n+1][1],"|")
     $seriesArray[$n][$Slink] = $itemArray[1]
     $seriesArray[$n][$Stitle] = $itemArray[2]
     $seriesArray[$n][$SnumMovies] = $itemArray[3]
   Next

As I mentioned - this is working so far - and presenting the data correctly in the GUI. Thank you M23 and wolf9228!! Next step is to work out Step 3 (save the updated variables) - which I think I pretty much have figured out, just need to finalize and test it (tomorrow).

@BrewManNH - I am curious as to why Assign is considered a "hack". Is it not a "standard" AutoIT function?

Thanks again folks.

Edited by gsbaker
Link to comment
Share on other sites

I noticed that in your assign statement you're trying to assign the data to an array element. In the help file it says you can't do that, it only works with variables, and not array elements.

In using the term "hack" I didn't mean it to imply that using it is a non-standard way of using the function, what I meant by it is that it can be done without using assign if you just access the values in the array elements directly. You already have the values that you need to use, so I was curious as to why you need to reassign those values to another variable. It makes the code that much harder to follow and usually harder to troubleshoot when something happens that you didn't expect.

For #3 you can always use the IniWrite commands to rewrite them to the .ini file, such as the IniWriteSection and use the array as the data to be written. Just reread them if needed later or use the array elements later in the script and use IniWriteSection to save them for the next time the script is run.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Well, I have got it working the way I need it to. Thank you all once again for your very valuable assistance.

@BrewManNH - not sure about the Help File. What I am really doing is assigning a value to a variable that is named the contents of an array element (the Key Value from the INI file). It seems to work - Yay!

Here are my final(?) code segments. I am sure there are much more efficient/elegant ways of doing it, but I am pretty happy with how few lines of code it takes as it is :).

Func ReadVariableFile()
; Purpose - Read variable values from saved .ini file
            
    FileCopy("MLMJ gsb Skin v1 Properties.ini", "Backup copy of MLMJ gsb Skin v1 Properties.ini")               ; keep a backup of last values

; Read single variables from ini File
    Global $variablesArray = ""
    $variablesArray = IniReadSection("MLMJ gsb Skin v1 Properties.ini","variables")
        For $n = 1 to $variablesArray[0][0]
            Assign ($variablesArray[$n][0],$variablesArray[$n][1], 2)
        Next
    
; Read Genre array variables
    Local $SectionData = "" 
    $SectionData = IniReadSection("MLMJ gsb Skin v1 Properties.ini","genreArray")
    $arraySize=$SectionData[0][0]
    Global $genreArray[$arraySize][3]
    Global $Glink = 0, $Gtitle=1, $GnumMovies=2
        For $n = 0 to $arraySize-1
            $itemArray = StringSplit($SectionData[$n+1][1],"|")
            $genreArray[$n][$Glink] = $itemArray[1]
            $genreArray[$n][$Gtitle] = $itemArray[2]
            $genreArray[$n][$GnumMovies] = $itemArray[3]
        Next

; Read Series array variables
    Local $SectionData = "" 
    $SectionData = IniReadSection("MLMJ gsb Skin v1 Properties.ini","seriesArray")
    $arraySize=$SectionData[0][0]
    Global $seriesArray[$arraySize][3]
    Global $Slink=0, $Stitle=1, $SnumMovies=2
        For $n = 0 to $arraySize-1
            $itemArray = StringSplit($SectionData[$n+1][1],"|")
            $seriesArray[$n][$Slink] = $itemArray[1]
            $seriesArray[$n][$Stitle] = $itemArray[2]
            $seriesArray[$n][$SnumMovies] = $itemArray[3]
        Next

EndFunc

Func WriteIniFile()
; Purpose -  Save updated values to INI file ***********************************************

; update Individual variable values
    For $n = 1 to $variablesArray[0][0]                                                 ; assign the values of the variables named by Key ([$n][0]) back to Value variable ([$n][1])                
        $variablesArray[$n][1] = Eval ($variablesArray[$n][0])                          
    Next

    $success = IniWriteSection("MLMJ gsb Skin v1 Properties.ini", "variables", $variablesArray)         ; update the values in the ini file using the updated array of variables
    
; update Genre array variables
    Local $SectionData = ""
        For $i = 0 To UBound($genreArray)-1
            $SectionData &= "genre" & $i & " = " & $genreArray[$i][0] & "|" & $genreArray[$i][1] & "|" & $genreArray[$i][2] & @LF
        Next
    IniWriteSection("MLMJ gsb Skin v1 Properties.ini","genreArray",$SectionData)

; update Series array variables
    Local $SectionData = ""
        For $i = 0 To UBound($seriesArray) - 1
            $SectionData &= "series" & $i & " = " & $seriesArray[$i][0] & "|" & $seriesArray[$i][1] & "|" & $seriesArray[$i][2] & @LF
        Next
    IniWriteSection("MLMJ gsb Skin v1 Properties.ini","seriesArray",$SectionData)
EndFunc
Edited by gsbaker
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...