Jump to content

_ReadIniSectionNames


TheSaint
 Share

Recommended Posts

_ReadIniSectionNames is just a little function I whipped up, that I thought I might as well share ... someone might find it useful. I had a need for it due to approaching the 32767 characters limit with the original INI function - IniReadSectionNames (see the Help file if you are not aware of this).

Enjoy! :)

Others have been there before me, and no doubt many others have also crafted their own solutions.

Here is two old ones I found with a quick search ... both different but kind of similar to mine. I've gone for the simplistic approach.

Test Example.au3

NOTE -  It should be obvious you need to provide your own INI file and its correct path for the $file variable. :)

#include <Array.au3>
#include "ReadIniSectionNames.au3"

Local $file = @ScriptDir & "\Settings.ini"
Local $names = _ReadIniSectionNames($file)
If Not @error Then
    _ArrayDisplay($names)
Else
    MsgBox(0, "Return Error", $names)
EndIf

Exit

ReadIniSectionNames.au3

Global $i, $INIfile, $INIlines, $INIread, $INIsection, $linetxt, $SectionNames

Func _ReadIniSectionNames($INIfile)
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $SectionNames = ""
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    If $SectionNames = "" Then
                        $SectionNames = $INIsection
                    Else
                        $SectionNames = $SectionNames & "|" & $INIsection
                    EndIf
                EndIf
            EndIf
        Next
        If $SectionNames = "" Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames = StringSplit($SectionNames, "|", 1)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

 

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

It has been suggested to me, that making $SectionNames an array at the start, and then adding to it, would be faster than concatenating strings and using StringSplit.

I did not find that to be the case, and doing so was actually significantly slower ... but maybe I am doing it wrong?

Here is what I did, with a 1.09 Mb INI file, that contains 2136 sections.

#include <Array.au3>

Global $i, $INIfile, $INIlines, $INIread, $INIsection, $linetxt

Local $file = "D:\Programs\KindEbook Wishlist\Jumbo (b).ini"
Local $names = _ReadIniSectionNames($file)
If Not @error Then
    _ArrayDisplay($names)
Else
    MsgBox(0, "Return Error", $names)
EndIf
Local $names = _ReadIniSectionNames_2($file)
If Not @error Then
    _ArrayDisplay($names)
Else
    MsgBox(0, "Return Error", $names)
EndIf

Exit

Func _ReadIniSectionNames($INIfile)
    Local $begin, $diff, $SectionNames
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $begin = TimerInit()
        $SectionNames = ""
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    If $SectionNames = "" Then
                        $SectionNames = $INIsection
                    Else
                        $SectionNames = $SectionNames & "|" & $INIsection
                    EndIf
                EndIf
            EndIf
        Next
        If $SectionNames = "" Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames = StringSplit($SectionNames, "|", 1)
            $diff = TimerDiff($begin) & " milliseconds"
            $diff = "Using StringSplit = " & $diff
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func _ReadIniSectionNames_2($INIfile)
    Local $begin, $diff_2, $s
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $begin = TimerInit()
        Local $SectionNames[1]
        $s = 0
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $s = $s + 1
                    _ArrayAdd($SectionNames, $INIsection, 1)
                EndIf
            EndIf
        Next
        If $s = 0 Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames[0] = $s
            $diff_2 = TimerDiff($begin) & " milliseconds"
            $diff_2 = "Using _ArrayAdd = " & $diff_2
            $diff = ClipGet() & @LF & $diff_2
            ClipPut($diff)
            MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_2

Here are some timing results. None are the same, no doubt due to vagaries of my PC and while connected to the web.

Using StringSplit = 475.797265465162 milliseconds
Using _ArrayAdd = 6029.33782085074 milliseconds

Using StringSplit = 469.701270439278 milliseconds
Using _ArrayAdd = 6282.41561636396 milliseconds

Using StringSplit = 500.060210392314 milliseconds
Using _ArrayAdd = 6137.26802103186 milliseconds

Using StringSplit = 484.184327357759 milliseconds
Using _ArrayAdd = 6135.25773119869 milliseconds

Using StringSplit = 489.524006129172 milliseconds
Using _ArrayAdd = 6130.73949420813 milliseconds

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

2 hours ago, TheSaint said:

It has been suggested to me, that making $SectionNames an array at the start, and then adding to it, would be faster than concatenating strings and using StringSplit.

Whoever said that is silly, any coder with half a brain would know that resizing an array is heaps slower than concatenating a string :muttley:

Anyway, I improved your function by using an Array, but in a different and more efficient way:

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

Global $i, $INIfile, $INIlines, $INIread, $INIsection, $linetxt, $SectionNames

Example()

Func Example()
    Local $aSections = _ReadIniSectionNames("Test.ini")
    _ArrayDisplay($aSections)
EndFunc

Func _ReadIniSectionNames($INIfile)
    $INIread = FileRead($INIfile)
    Local $iSectionCount = StringCount($INIread, '[')
    Local $aSections[$iSectionCount + 1]
    $aSections[0] = 0
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $aSections[0] += 1
                    $aSections[$aSections[0]] = $INIsection
                EndIf
            EndIf
        Next
        If $aSections[0] = 0 Then
            Return SetError(2, 0, -2)
        Else
            If $aSections[0] < $iSectionCount Then ReDim $aSections[$aSections[0] + 1]
            Return $aSections
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func StringCount($sMasterString, $sString)
    Local $iPos = 0
    Local $iCount = 0
    While True
        $iPos = StringInStr($sMasterString, $sString, $STR_NOCASESENSEBASIC, 1, $iPos + 1)
        If @error Or $iPos = 0 Then ExitLoop
        $iCount += 1
    WEnd
    Return $iCount
EndFunc

 

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Another point, someone might think that my StringCount function is not correct for detecting the number of sections in the file... and they would be right, it is just an approxmation, not an absolute value of the number of sections in the INI file. As everyone knows how high my coding standards are, I have obviously accounted for the possibility of an over-estimation, so an INI file with these contents would still work:

[Foobar1]
error=[
[Foobar2]
[Foobar3]

;)

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Okay, adding in TheDcoder's ReDim method ... with a slight adaption by me to match the other two etc. By the way, my INI file has increased to 2139 sections, since I last tested ... 3 acquisitions from Amazon.

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

Global $i, $INIfile, $INIlines, $INIread, $INIsection, $linetxt

Local $file = "D:\Programs\KindEbook Wishlist\Jumbo (b).ini"
Local $names = _ReadIniSectionNames($file)
If Not @error Then
    _ArrayDisplay($names)
Else
    MsgBox(0, "Return Error", $names)
EndIf
Local $names = _ReadIniSectionNames_2($file)
If Not @error Then
    _ArrayDisplay($names)
Else
    MsgBox(0, "Return Error", $names)
EndIf
Local $names = _ReadIniSectionNames_3($file)
If Not @error Then
    _ArrayDisplay($names)
Else
    MsgBox(0, "Return Error", $names)
EndIf

Exit

Func _ReadIniSectionNames($INIfile)
    Local $begin, $diff, $SectionNames
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $begin = TimerInit()
        $SectionNames = ""
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    If $SectionNames = "" Then
                        $SectionNames = $INIsection
                    Else
                        $SectionNames = $SectionNames & "|" & $INIsection
                    EndIf
                EndIf
            EndIf
        Next
        If $SectionNames = "" Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames = StringSplit($SectionNames, "|", 1)
            $diff = TimerDiff($begin) & " milliseconds"
            $diff = "Using StringSplit = " & $diff
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func _ReadIniSectionNames_2($INIfile)
    Local $begin, $diff_2, $s
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $begin = TimerInit()
        Local $SectionNames[1]
        $s = 0
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $s = $s + 1
                    _ArrayAdd($SectionNames, $INIsection, 1)
                EndIf
            EndIf
        Next
        If $s = 0 Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames[0] = $s
            $diff_2 = TimerDiff($begin) & " milliseconds"
            $diff_2 = "Using _ArrayAdd = " & $diff_2
            $diff = ClipGet() & @LF & $diff_2
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_2

Func _ReadIniSectionNames_3($INIfile)
    Local $begin, $diff_3
    $INIread = FileRead($INIfile)
    Local $iSectionCount = StringCount($INIread, '[')
    Local $SectionNames[$iSectionCount + 1]
    $SectionNames[0] = 0
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $begin = TimerInit()
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $SectionNames[0] += 1
                    $SectionNames[$SectionNames[0]] = $INIsection
                EndIf
            EndIf
        Next
        If $SectionNames[0] = 0 Then
            Return SetError(2, 0, -2)
        Else
            If $SectionNames[0] < $iSectionCount Then ReDim $SectionNames[$SectionNames[0] + 1]
            $diff_3 = TimerDiff($begin) & " milliseconds"
            $diff_3 = "Using ReDim = " & $diff_3
            $diff = ClipGet() & @LF & $diff_3
            ClipPut($diff)
            MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_3

Func StringCount($sMasterString, $sString)
    Local $iPos = 0
    Local $iCount = 0
    While True
        $iPos = StringInStr($sMasterString, $sString, $STR_NOCASESENSEBASIC, 1, $iPos + 1)
        If @error Or $iPos = 0 Then ExitLoop
        $iCount += 1
    WEnd
    Return $iCount
EndFunc

Not much in it for all that extra brain work. Times are so variable. So as I am fond of saying - Simple is best. :P

Using StringSplit = 455.895273238447 milliseconds
Using _ArrayAdd = 6192.77094369345 milliseconds
Using ReDim = 425.429429119466 milliseconds

Using StringSplit = 476.165900520144 milliseconds
Using _ArrayAdd = 7039.70260981331 milliseconds
Using ReDim = 467.105465260447 milliseconds

Using StringSplit = 540.775337823308 milliseconds
Using _ArrayAdd = 8396.5929519435 milliseconds
Using ReDim = 494.923895292899 milliseconds

Using StringSplit = 795.332588690522 milliseconds
Using _ArrayAdd = 6796.17676296643 milliseconds
Using ReDim = 576.076445080135 milliseconds

Using StringSplit = 470.990264348198 milliseconds
Using _ArrayAdd = 7487.17702961245 milliseconds
Using ReDim = 531.051359464644 milliseconds

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

Those results are pretty wacky, AutoIt is performing some memory tradeoff to make string concatenation more efficient, which is good for people who want simple and fast code and don't mind some extra memory use.

Anyway, the only remotely expensive operation in the timed parts of my code is the ReDim operation, which is only done once when the $iSectionCount guess is wrong (and it is right most of the time assuming not many INI files have the [ character as a value in one of their keys). The only other modification is:

$SectionNames[0] += 1
$SectionNames[$SectionNames[0]] = $INIsection

Which is supposed to be an almost instant operation, certainly when compared to string concatenation :lol:

So there are other factors at play, and performance is not always reliable, especially when attempting to measure it according to my personal experience. In any case, my code doesn't depend on assumptions and trade-offs being made by the interperter (AutoIt) and it is pretty solid.

Edited by TheDcoder

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Passing nearby I can't resist pointing out that for such volume of data which will obviously have to be searched, most probably using various if not contrived ways/criterion, I'd use SQLite without one µsecond hesitation.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

41 minutes ago, jchd said:

I'd use SQLite without one µsecond hesitation.

TheSaint has already gone that route, but he prefers to stick to simpler INI functions as SQLite is complex and does not bode well with his mindset of simple programming as he explained here :):

 

 

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

That's a matter of taste, of course.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

I'd load the ini in a 3D array, with the 1 table ( $aArray[0][0][0] ) as the index (ReadIniSectionNames) , or load it to a script dictionary. That way you'd have the ini in memory and you could dump it to file as you go. Then again,  SQLite ala ini  functions can be coded but it would not be plain text. I use as a preference ini files but not as a database, I mean, 32k of initialization data !, that's more like a db !.Then again I look at @TheSaint's avatar and it's a beautiful sight. I have trouble with things that are not as I want'em.

Bottom line: an INI file is for configuration/initialization, not a database nor meant as one. ( now that is harsh but I felt needed to be said ) :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Simple and faster...

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

;For $i = 1 To 1000
;   IniWrite("TestIni.ini", "Numbers " & $i, "Results " & $i, $i)
;Next
$Path = "TestIni.ini"

$time = TimerInit()
MyIniReadSectionNames($Path)
MsgBox(0,"","My Example: " & TimerDiff($time))

$time = TimerInit()
_ReadIniSectionNamesTheSaint($Path)
MsgBox(0,"","TheSaint Example: " & TimerDiff($time))

$time = TimerInit()
_ReadIniSectionNamesTheDcoder($Path)
MsgBox(0,"","TheDcoder Example: " & TimerDiff($time))

Func MyIniReadSectionNames($Path)
    FileReadToArray($Path)
    Local $Array[@extended/2]
    $File = FileRead($Path)
    If Not @error Then
        $Str = StringRegExp($File, "(?!\[).+(?=\])", 3)
        If IsArray($Str) Then
            For $i = 0 To UBound($Str)-1
                $Array[$i] = $Str[$i]
            Next
            Return $Array
        EndIf
    EndIf
EndFunc

Func _ReadIniSectionNamesTheSaint($INIfile)
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $SectionNames = ""
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    If $SectionNames = "" Then
                        $SectionNames = $INIsection
                    Else
                        $SectionNames = $SectionNames & "|" & $INIsection
                    EndIf
                EndIf
            EndIf
        Next
        If $SectionNames = "" Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames = StringSplit($SectionNames, "|", 1)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func _ReadIniSectionNamesTheDcoder($INIfile)
    $INIread = FileRead($INIfile)
    Local $iSectionCount = StringCount($INIread, '[')
    Local $aSections[$iSectionCount + 1]
    $aSections[0] = 0
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $aSections[0] += 1
                    $aSections[$aSections[0]] = $INIsection
                EndIf
            EndIf
        Next
        If $aSections[0] = 0 Then
            Return SetError(2, 0, -2)
        Else
            If $aSections[0] < $iSectionCount Then ReDim $aSections[$aSections[0] + 1]
            Return $aSections
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func StringCount($sMasterString, $sString)
    Local $iPos = 0
    Local $iCount = 0
    While True
        $iPos = StringInStr($sMasterString, $sString, $STR_NOCASESENSEBASIC, 1, $iPos + 1)
        If @error Or $iPos = 0 Then ExitLoop
        $iCount += 1
    WEnd
    Return $iCount
EndFunc

 

Edited by Progh0st
Link to comment
Share on other sites

On 12/11/2019 at 12:26 AM, argumentum said:

Bottom line: an INI file is for configuration/initialization, not a database nor meant as one. ( now that is harsh but I felt needed to be said ) :) 

Well you say that, and it was certainly true once upon a time, but INI files can be quite huge now, and no longer limited like they used to be, and far easier to troubleshoot or apply a manual quick fix using a text editor.

So I would say, if your database needs are simple, than INI is quite fine. If you want to do all sorts of fancy things then go SQL.

If they ever bring out a database program that gives quick visual access and editing with Notepad, that is not INI and works better than INI ... and especially isn't XML ... then I would certainly be keen to give it a go. It must also support words that contain single and double quotes without having to do anything special. I was almost in love with SQL until I discovered blank database entries due an apostrophe in some entries, that I then had to code for to get around ... in what is supposedly a database program. I can almost accept the issue when it comes to program settings (INI file etc), but a true database language should accept apostrophes, which are as common as dog's balls, off the bat, without anything special needing to be done ... we are 2019 after all, nearly 2020 ... it shouldn't be required to use escape characters ... in fact if you want to use such characters as other than text, then a command should be required to specify so, not the other way around in this day and age ... but hey it is the digital age of the nerd ... so it will be a while yet before that idea finally catches on.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

On 12/12/2019 at 11:18 AM, Progh0st said:

Simple and faster...

Not for me it wasn't, but thanks. :)

I did a quick adaption of your code to add to my mix ... which included an adjustment to return the count in the first element of the array. I'm not sure if your code is taking into account that a '[' or ']' could exist beyond the section name ... RegEx is not a strong point of mine?

Part of the reason your code takes so long to finish, is all the extra blank sections at the end, that get returned ... not sure what that is about ... maybe some null character? Of the non blanks, your code returns 2140 section names, when it should be 2139, but I discovered one (1797) was an entry not a section, and it contained a '[' and looked truncated.

Quote

title=Dead in Damascus: A Special Operations Group Short Story ([#0

Like you, I also changed where TimerInit() is used for each option.

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

Global $begin, $diff, $filepth, $i, $INIfile, $INIlines, $INIread, $INIsection, $linetxt

$filepth = "D:\Programs\KindEbook Wishlist\Jumbo (b).ini"
$begin = TimerInit()
Local $names = _ReadIniSectionNames($filepth)  ; TheSaint
If Not @error Then
    _ArrayDisplay($names, "Using StringSplit")
Else
    MsgBox(0, "Return Error", $names)
EndIf
$begin = TimerInit()
Local $names = _ReadIniSectionNames_2($filepth)  ; TheSaint
If Not @error Then
    _ArrayDisplay($names, "Using _ArrayAdd")
Else
    MsgBox(0, "Return Error", $names)
EndIf
$begin = TimerInit()
Local $names = _ReadIniSectionNames_3($filepth)  ; TheDcoder
If Not @error Then
    _ArrayDisplay($names, "Using ReDim")
Else
    MsgBox(0, "Return Error", $names)
EndIf
$begin = TimerInit()
Local $names = _ReadIniSectionNames_4($filepth)  ; Progh0st
If Not @error Then
    _ArrayDisplay($names, "Using StringRegExp")
Else
    MsgBox(0, "Return Error", $names)
EndIf

MsgBox(0, "Time Taken", $diff)

Exit

Func _ReadIniSectionNames($INIfile)
    Local $SectionNames
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        ;$begin = TimerInit()
        $SectionNames = ""
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    If $SectionNames = "" Then
                        $SectionNames = $INIsection
                    Else
                        $SectionNames = $SectionNames & "|" & $INIsection
                    EndIf
                EndIf
            EndIf
        Next
        If $SectionNames = "" Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames = StringSplit($SectionNames, "|", 1)
            $diff = TimerDiff($begin) & " milliseconds"
            $diff = "Using StringSplit = " & $diff
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func _ReadIniSectionNames_2($INIfile)
    Local $diff_2, $s
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        Local $SectionNames[1]
        $s = 0
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $s = $s + 1
                    _ArrayAdd($SectionNames, $INIsection, 1)
                EndIf
            EndIf
        Next
        If $s = 0 Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames[0] = $s
            $diff_2 = TimerDiff($begin) & " milliseconds"
            $diff_2 = "Using _ArrayAdd = " & $diff_2
            $diff = ClipGet() & @LF & $diff_2
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_2

Func _ReadIniSectionNames_3($INIfile)
    Local $diff_3
    $INIread = FileRead($INIfile)
    Local $iSectionCount = StringCount($INIread, '[')
    Local $SectionNames[$iSectionCount + 1]
    $SectionNames[0] = 0
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $SectionNames[0] += 1
                    $SectionNames[$SectionNames[0]] = $INIsection
                EndIf
            EndIf
        Next
        If $SectionNames[0] = 0 Then
            Return SetError(2, 0, -2)
        Else
            If $SectionNames[0] < $iSectionCount Then ReDim $SectionNames[$SectionNames[0] + 1]
            $diff_3 = TimerDiff($begin) & " milliseconds"
            $diff_3 = "Using ReDim = " & $diff_3
            $diff = ClipGet() & @LF & $diff_3
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_3

Func StringCount($sMasterString, $sString)
    Local $iPos = 0
    Local $iCount = 0
    While True
        $iPos = StringInStr($sMasterString, $sString, $STR_NOCASESENSEBASIC, 1, $iPos + 1)
        If @error Or $iPos = 0 Then ExitLoop
        $iCount += 1
    WEnd
    Return $iCount
EndFunc

Func _ReadIniSectionNames_4($INIfile)
    Local $diff_4
    FileReadToArray($INIfile)
    Local $Array[@extended/2]
    $INIread = FileRead($INIfile)
    If Not @error Then
        $Str = StringRegExp($INIread, "(?!\[).+(?=\])", 3)
        If IsArray($Str) Then
            $Array[0] = UBound($Str)-1
            For $i = 0 To $Array[0]
                $Array[$i + 1] = $Str[$i]
            Next
            $diff_4 = TimerDiff($begin) & " milliseconds"
            $diff_4 = "Using StringRegExp = " & $diff_4
            $diff = ClipGet() & @LF & $diff_4
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $Array
        Else
            Return SetError(2, 0, -2)
        EndIf
    Else
        Return SetError(1, 0, -1)
    EndIf
EndFunc ;=> _ReadIniSectionNames_4

LOL, my computer has had a rest for 6 days, but I doubt that has had any impact on the following results ... unless extra services are running in the background doing update checks etc.

Using StringSplit = 640.6785096822 milliseconds
Using _ArrayAdd = 6454.83544745537 milliseconds
Using ReDim = 1706.50690023384 milliseconds
Using StringRegExp = 7994362.73136458 milliseconds

Using StringSplit = 636.893856451052 milliseconds
Using _ArrayAdd = 6528.23744521161 milliseconds
Using ReDim = 1033.22200554673 milliseconds
Using StringRegExp = 8221753.24552446 milliseconds

Using StringSplit = 644.393122252901 milliseconds
Using _ArrayAdd = 6502.97304171843 milliseconds
Using ReDim = 1058.29471881132 milliseconds
Using StringRegExp = 10782.6687457684 milliseconds

Using StringSplit = 630.238764925112 milliseconds
Using _ArrayAdd = 6401.26048613133 milliseconds
Using ReDim = 1064.84413495484 milliseconds
Using StringRegExp = 10225.6574913401 milliseconds

Using StringSplit = 1042.68056666581 milliseconds
Using _ArrayAdd = 6550.86549366992 milliseconds
Using ReDim = 1044.97347670779 milliseconds
Using StringRegExp = 10513.411557692 milliseconds

Using StringSplit = 710.721013304039 milliseconds
Using _ArrayAdd = 6613.37862629376 milliseconds
Using ReDim = 1086.44492039326 milliseconds
Using StringRegExp = 10129.1801679256 milliseconds

The first block of 4 out of 6 results above, were done using the GO option in SciTE, the other (last) two were done executing the AU3 file.

The following is a typical section in my test INI file.

Quote

[B00DMCPRQA]
date=15/01/2015 6:46:08 PM
url=http://www.amazon.com/dp/B00DMCPRQA/etc
title=Stolen Crown: A Novel of Mithgar
author=Dennis L. McKiernan
start=$14.82
low=$6.39
high=$14.88
current=$6.39
query=17/05/2015 12:58:29 AM
bought=Paid $6.39 on 17/05/2015 1:01:16 AM
changed=17/05/2015 12:58:29 AM
previous=24/02/2015 6:35:58 AM
last=$6.39

 

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

10 hours ago, TheSaint said:

if your database needs are simple

...I used to have a happy face DB. So it happens, chr(1) is a pappy face in Terminal font. the chr(2) is a color inverted happy face too. Those where the delimiters for my databaseish scheme. Read, split and was human readable.
In your case, a TAB delimited table may be easier than an INI styled file. You can use the _array to/from file().  So it would meet your requirement of notepad editable database.
Basically, if you can read/write to file, is the bases of holding data ( data base ). INI styled or what not is all the same in the case of notapad editable db :) 

As the DB grows, searching may need flexibility in querying the data. SQL92 was to get us all to agree but you are a one man team. I use ( at times ) what others came up with as a "ready made" solution, ex: SQLite.

A blob in an INI file would take Str2Bin to keep it a one-liner. 

ok, new bottom line: Use industry standards or come up with your own. If is functional, it functioned. :thumbsup:

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

While I don't have a 1 Mb Ini file to test it on, it looks like this RegEx is simpler and faster at least on smaller files (210 Kb) by ~20 milliseconds (with file handles or the file name)

Func _Ini_ReadSectionNames($sFileName)

;~  If Not FileExists($sFileName) Then Return SetError(1, 0, False)

    Local $sContents = FileRead($sFileName)

    ; (?m)                  - Allows new lines to be used
    ;     ^                 - Starting at the beginning of a line
    ;      \[               - Match an open square bracket
    ;        ([^\]]+)       - Capture everything that isn't a closing square bracket (at least 1 character)
    ;                \]     - Match a closing square bracket
    ;                  \s*  - Match as much blank space as you need, Taylor
    ;                     $ - Match the end of a line
    Local $aSections = StringRegExp($sContents, "(?m)^\[([^\]]+)\]\s*$", 3)

    Return SetError(@error, @extended, $aSections)

EndFunc

I ran some tests, but I'm not the expert of giant files :)

Edit: Just realized that you return a 1-based array. Mine's 0-based (personal preference, it's in my ini file). It also works with brackets strewn about in the data.

Edited by seadoggie01

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

Spoiler
Quote

Using StringSplit = 640.6785096822 milliseconds
Using _ArrayAdd = 6454.83544745537 milliseconds
Using ReDim = 1706.50690023384 milliseconds
Using StringRegExp = 7994362.73136458 milliseconds

Using StringSplit = 636.893856451052 milliseconds
Using _ArrayAdd = 6528.23744521161 milliseconds
Using ReDim = 1033.22200554673 milliseconds
Using StringRegExp = 8221753.24552446 milliseconds

Using StringSplit = 644.393122252901 milliseconds
Using _ArrayAdd = 6502.97304171843 milliseconds
Using ReDim = 1058.29471881132 milliseconds
Using StringRegExp = 10782.6687457684 milliseconds

Using StringSplit = 630.238764925112 milliseconds
Using _ArrayAdd = 6401.26048613133 milliseconds
Using ReDim = 1064.84413495484 milliseconds
Using StringRegExp = 10225.6574913401 milliseconds

Using StringSplit = 1042.68056666581 milliseconds
Using _ArrayAdd = 6550.86549366992 milliseconds
Using ReDim = 1044.97347670779 milliseconds
Using StringRegExp = 10513.411557692 milliseconds

Using StringSplit = 710.721013304039 milliseconds
Using _ArrayAdd = 6613.37862629376 milliseconds
Using ReDim = 1086.44492039326 milliseconds
Using StringRegExp = 10129.1801679256 milliseconds

 

Good to see that my Array approach ins't falling behind too much with a consistent 2nd position :lol:

Also surprised to see that RegEx is slower than _ArrayAdd :blink:

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

2 hours ago, TheDcoder said:

Good to see that my Array approach ins't falling behind too much with a consistent 2nd position :lol:

Also surprised to see that RegEx is slower than _ArrayAdd :blink:

Yep, you did good bud.

I suspect the StringRegEx is returning every line of my INI file, but only the lines with the actual section name (plus one other) have visible values. So clearly to my mind at least, the RegEx is wrong.

@seadoggie01 has probably given the correct one. I will test that a bit later. Need to put my legs up, the holiday was physically tough on me in a number of ways leg related especially.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

On 12/16/2019 at 3:19 AM, TheSaint said:

Not for me it wasn't, but thanks. :)

I did a quick adaption of your code to add to my mix ... which included an adjustment to return the count in the first element of the array. I'm not sure if your code is taking into account that a '[' or ']' could exist beyond the section name ... RegEx is not a strong point of mine?

Part of the reason your code takes so long to finish, is all the extra blank sections at the end, that get returned ... not sure what that is about ... maybe some null character? Of the non blanks, your code returns 2140 section names, when it should be 2139, but I discovered one (1797) was an entry not a section, and it contained a '[' and looked truncated.

try this:

Func MyIniReadSectionNames($Path)
    $File = FileRead($Path)
    If Not @error Then
        $Str = StringRegExp($File, "(?m)^\[{1}([^\[\]]+)\]{1}", 3)
        If IsArray($Str) Then
            $ArraySize = UBound($Str)
            Local $Array[$ArraySize]
            For $i = 0 To $ArraySize-1
                $Array[$i] = $Str[$i]
            Next
            Return $Array
        EndIf
    EndIf
EndFunc

It will match anything between [....] For Section names only. Hopefully. Test speed please 😃

A little faster, using it directly like (seadoggie01)

Func MyIniReadSectionNames($Path)
    $File = FileRead($Path)
    If Not @error Then
        $Str = StringRegExp($File, "(?m)^\[{1}([^\[\]]+)\]{1}", 3)
        If IsArray($Str) Then
            Return $Str
        EndIf
    EndIf
EndFunc

 

Edited by Progh0st
Link to comment
Share on other sites

Okay, I finally got a moment to test the last two methods ... and wow.

Quote

(TheSaint) - Using StringSplit = 684.060711735989 milliseconds
(TheSaint) - Using _ArrayAdd = 7170.40892686649 milliseconds
(TheDcoder) - Using ReDim = 1162.42674914262 milliseconds
(Progh0st) - Using StringRegExp = 256.445891132238 milliseconds
(seadoggie01) - Using StringRegExp_2 = 280.931245875895 milliseconds

@Progh0st appears to be the winner, with @seadoggie01 not far behind. Bad luck @TheDcoder looks like you and I are out in the cold.

Here are the amended methods ... five in all. My INI file has also increased to 2241 sections.

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

Global $begin, $diff, $error, $filepth, $i, $INIfile, $INIlines, $INIread
Global $INIsection, $linetxt, $method, $names, $next

; Current sections = 2241

$filepth = "D:\Programs\KindEbook Wishlist\Jumbo (b).ini"

If FileExists($filepth) Then
    $diff = ""
    ClipPut($diff)
    $method = "StringSplit"
    While 1
        $error = ""
        StartFresh()
        If $method = "StringSplit" Then
            $names = _ReadIniSectionNames($filepth)  ; TheSaint
            If @error Then $error = 1
            $next = "_ArrayAdd"
        ElseIf $method = "_ArrayAdd" Then
            $names = _ReadIniSectionNames_2($filepth)  ; TheSaint
            If @error Then $error = 1
            $next = "ReDim"
        ElseIf $method = "ReDim" Then
            $names = _ReadIniSectionNames_3($filepth)  ; TheDcoder
            If @error Then $error = 1
            $next = "StringRegExp"
        ElseIf $method = "StringRegExp" Then
            $names = _ReadIniSectionNames_4($filepth)  ; Progh0st
            If @error Then $error = 1
            $next = "StringRegExp_2"
        ElseIf $method = "StringRegExp_2" Then
            $names = _Ini_ReadSectionNames_5($filepth)  ; seadoggie01
            If @error Then $error = 1
            $next = ""
        EndIf
        If $error = 1 Then
            MsgBox(0, "Return Error", $names)
        Else
            _ArrayDisplay($names, "Using " & $method)
        EndIf
        If $next = "" Then ExitLoop
        $method = $next
    WEnd
    MsgBox(0, "Time Taken", $diff)
Else
    MsgBox(0, "Source Error", "INI file path not found!")
EndIf

Exit

Func StartFresh()
    $begin = TimerInit()
    $names = ""
    $INIread = ""
    $INIlines = ""
    $INIsection = ""
EndFunc ;=> StartFresh

Func _ReadIniSectionNames($INIfile) ; TheSaint
    Local $SectionNames
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        $SectionNames = ""
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    If $SectionNames = "" Then
                        $SectionNames = $INIsection
                    Else
                        $SectionNames = $SectionNames & "|" & $INIsection
                    EndIf
                EndIf
            EndIf
        Next
        If $SectionNames = "" Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames = StringSplit($SectionNames, "|", 1)
            $diff = TimerDiff($begin) & " milliseconds"
            $diff = "Using StringSplit = " & $diff
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames

Func _ReadIniSectionNames_2($INIfile) ; TheSaint
    Local $diff_2, $s
    $INIread = FileRead($INIfile)
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        Local $SectionNames[1]
        $s = 0
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $s = $s + 1
                    _ArrayAdd($SectionNames, $INIsection, 1)
                EndIf
            EndIf
        Next
        If $s = 0 Then
            Return SetError(2, 0, -2)
        Else
            $SectionNames[0] = $s
            $diff_2 = TimerDiff($begin) & " milliseconds"
            $diff_2 = "Using _ArrayAdd = " & $diff_2
            $diff = ClipGet() & @LF & $diff_2
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_2

Func _ReadIniSectionNames_3($INIfile) ; TheDcoder
    Local $diff_3
    $INIread = FileRead($INIfile)
    Local $iSectionCount = StringCount($INIread, '[')
    Local $SectionNames[$iSectionCount + 1]
    $SectionNames[0] = 0
    $INIlines = StringSplit($INIread, @LF, 1)
    If @error Then
        Return SetError(1, 0, -1)
    Else
        For $i = 1 To $INIlines[0]
            $linetxt = $INIlines[$i]
            If StringLeft($linetxt, 1) = "[" Then
                $INIsection = StringTrimLeft($linetxt, 1)
                $INIsection = StringStripCR($INIsection)
                $INIsection = StringTrimRight($INIsection, 1)
                If $INIsection <> "" Then
                    $SectionNames[0] += 1
                    $SectionNames[$SectionNames[0]] = $INIsection
                EndIf
            EndIf
        Next
        If $SectionNames[0] = 0 Then
            Return SetError(2, 0, -2)
        Else
            If $SectionNames[0] < $iSectionCount Then ReDim $SectionNames[$SectionNames[0] + 1]
            $diff_3 = TimerDiff($begin) & " milliseconds"
            $diff_3 = "Using ReDim = " & $diff_3
            $diff = ClipGet() & @LF & $diff_3
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $SectionNames
        EndIf
    EndIf
EndFunc ;=> _ReadIniSectionNames_3

Func StringCount($sMasterString, $sString)
    Local $iPos = 0
    Local $iCount = 0
    While True
        $iPos = StringInStr($sMasterString, $sString, $STR_NOCASESENSEBASIC, 1, $iPos + 1)
        If @error Or $iPos = 0 Then ExitLoop
        $iCount += 1
    WEnd
    Return $iCount
EndFunc

Func _ReadIniSectionNames_4($INIfile) ; Progh0st
    Local $ArraySize, $diff_4, $Str
    $INIread = FileRead($INIfile)
    If Not @error Then
        $Str = StringRegExp($INIread, "(?m)^\[{1}([^\[\]]+)\]{1}", 3)
        If IsArray($Str) Then
            $ArraySize = UBound($Str)
            Local $Array[$ArraySize + 1]
            For $i = 0 To $ArraySize - 1
                $Array[$i + 1] = $Str[$i]
            Next
            $Array[0] = UBound($Array) - 1
            $diff_4 = TimerDiff($begin) & " milliseconds"
            $diff_4 = "Using StringRegExp = " & $diff_4
            $diff = ClipGet() & @LF & $diff_4
            ClipPut($diff)
            ;MsgBox(0, "Time Taken", $diff)
            Return $Array
        Else
            Return SetError(2, 0, -2)
         EndIf
    Else
        Return SetError(1, 0, -1)
    EndIf
EndFunc ;=> _ReadIniSectionNames_4

Func _Ini_ReadSectionNames_5($INIfile) ; seadoggie01
    Local $diff_5, $SectionNames
    ; (?m)                  - Allows new lines to be used
    ;     ^                 - Starting at the beginning of a line
    ;      \[               - Match an open square bracket
    ;        ([^\]]+)       - Capture everything that isn't a closing square bracket (at least 1 character)
    ;                \]     - Match a closing square bracket
    ;                  \s*  - Match as much blank space as you need, Taylor
    ;                     $ - Match the end of a line
    $INIread = FileRead($INIfile)
    If Not @error Then
        $SectionNames = StringRegExp($INIread, "(?m)^\[([^\]]+)\]\s*$", 3)
        $ArraySize = UBound($SectionNames)
        _ArrayInsert($SectionNames, 0, $ArraySize, 0)
        $diff_5 = TimerDiff($begin) & " milliseconds"
        $diff_5 = "Using StringRegExp_2 = " & $diff_5
        $diff = ClipGet() & @LF & $diff_5
        ClipPut($diff)
        ;MsgBox(0, "Time Taken", $diff)
        Return $SectionNames
    Else
        Return SetError(1, 0, -1)
    EndIf
EndFunc ;=> _ReadIniSectionNames_5

A few more run through results.

Quote

Using StringSplit = 807.637626825819 milliseconds
Using _ArrayAdd = 7831.22166886005 milliseconds
Using ReDim = 1129.22870487446 milliseconds
Using StringRegExp = 260.368168117246 milliseconds
Using StringRegExp_2 = 277.868502960754 milliseconds

Using StringSplit = 806.031606769614 milliseconds
Using _ArrayAdd = 7577.08711952254 milliseconds
Using ReDim = 1693.85227318807 milliseconds
Using StringRegExp = 263.037700307073 milliseconds
Using StringRegExp_2 = 516.418390957136 milliseconds

Using StringSplit = 1220.27296197038 milliseconds
Using _ArrayAdd = 6791.55469376872 milliseconds
Using ReDim = 1154.44149945995 milliseconds
Using StringRegExp = 277.211103779369 milliseconds
Using StringRegExp_2 = 266.611617165123 milliseconds

Using StringSplit = 670.33335668022 milliseconds
Using _ArrayAdd = 7214.99595115831 milliseconds
Using ReDim = 1135.47891223168 milliseconds
Using StringRegExp = 265.972035344729 milliseconds
Using StringRegExp_2 = 266.983324178896 milliseconds

Using StringSplit = 844.649200737762 milliseconds
Using _ArrayAdd = 6827.6624974042 milliseconds
Using ReDim = 1132.80938004185 milliseconds
Using StringRegExp = 253.72966516878 milliseconds
Using StringRegExp_2 = 263.708001715382 milliseconds

Using StringSplit = 1098.22465357521 milliseconds
Using _ArrayAdd = 7380.63596919685 milliseconds
Using ReDim = 1084.97406652388 milliseconds
Using StringRegExp = 263.821664190668 milliseconds
Using StringRegExp_2 = 269.532435584096 milliseconds

The first 3 results were using the GO option in SciTE

The next two results were executing the AU3 file.

The last two results were executing the compiled AU3 file.

Still a bit of variation between runs, but not as much with the StringRegExp methods.

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

17 minutes ago, TheSaint said:

@Progh0st appears to be the winner, with @seadoggie01 not far behind. Bad luck @TheDcoder looks like you and I are out in the cold.

Indeed, there is good reason why RegEx is faster, it has less overhead processing strings as it runs in pure machine code, so we cannot compare both methods really.

If everything is written in a low-level language, my method would be fastest... a lot faster than RegEx :D

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

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...