Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

INI File functions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • INI File functions

    Some functions on INI file handling.
    Please feel free to use them as you prefer.

    Name this file EOINI.inc

    Code:
    #If 0
      '===========================================================================
      ' File Name   : EOINI.INC
      ' Date        : 11/07/2002
      ' Version     : 01.00.00
      ' Description : INI File handling routines
      ' Author      : Eros Olmi 
      ' email       : [email protected]
      ' Compiled    : PBWin 7.00
      '             : PBCC 3.00  
      ' Depends from: WIN32API.INC
      '---------------Date-------Version--Text------------------------------------
      ' Notes       : 11/07/2002 01.00.00 
      '---------------Date-------Version--Text------------------------------------
      ' Edit History: 11/07/2002 01.00.00 Initial coding
      '===========================================================================
    
    #ENDIF
    
    #IF NOT %DEF(%EOIniINC)
      %EOIniINC = 1
    
      $INCLUDE "WIN32API.INC"
    
      '---------------------------------------------------------------------------
      ' Determines if a line of text is a Comment Line (ex. "; Comment")
      ' Returns: %TRUE  if line is a comment line
      '          %FALSE if line is not a comment line
      '---------------------------------------------------------------------------
      FUNCTION INI_LineIsComment(BYVAL TextLine AS STRING) AS LONG
        FUNCTION = %FALSE
        IF TextLine = "" THEN EXIT FUNCTION                                      
        TextLine = UCASE$(LTRIM$(TextLine))
        IF LEFT$(TextLine, 1) = ";" THEN
          FUNCTION = %TRUE
        END IF
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Determines if a line of text is a valid section (ex. "[Section]")
      ' Returns: %TRUE  if line is a Section line
      '          %FALSE if line is not a Section line
      '---------------------------------------------------------------------------
      FUNCTION INI_LineIsSection(BYVAL TextLine AS STRING) AS LONG
        FUNCTION = %FALSE
        IF TextLine = "" THEN EXIT FUNCTION
        IF LEFT$(TextLine, 1) = "[" THEN
          IF RIGHT$(TextLine, 1) = "]" THEN
            FUNCTION = %TRUE
          END IF
        END IF
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Determines if a line of text is a valid Key (ex. "KeyName=Key value")
      ' Returns: %TRUE  if line is a Key line
      '          %FALSE if line is not a Key line
      '---------------------------------------------------------------------------
      FUNCTION INI_LineIsKey(BYVAL TextLine AS STRING) AS LONG
        DIM Looper AS LONG
    
        FUNCTION = %FALSE
        IF INI_LineIsSection(TextLine) = %FALSE THEN
          FOR Looper = 1 TO LEN(TextLine)
            IF MID$(TextLine, Looper, 1) <> "=" THEN ITERATE FOR
            FUNCTION = %TRUE
            EXIT FOR
          NEXT Looper
        END IF
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Determines if a section exists in a given INI file
      ' Returns: %TRUE  if lSection exists inside IniFile
      '          %FALSE if lSection does not exists inside IniFile
      '---------------------------------------------------------------------------
      FUNCTION INI_SectionExists(BYVAL IniFile AS STRING, BYVAL lSection AS STRING) AS LONG
        DIM InputData AS STRING
        DIM FileID AS LONG
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        FUNCTION = %FALSE
        ON ERROR RESUME NEXT
        OPEN IniFIle FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF UCASE$(InputData) = "[" + UCASE$(lSection) + "]" THEN
            FUNCTION = %TRUE
            EXIT DO
          END IF
        LOOP
        CLOSE #FileID
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Determines if a Key exists inside lSection in a given INI file
      ' Returns: %TRUE  if lKey exists inside lSection section
      '          %FALSE if lKey does not exists inside lSection section
      '---------------------------------------------------------------------------
      FUNCTION INI_KeyExists(BYVAL IniFile AS STRING, BYVAL lSection AS STRING, BYVAL lKey AS STRING) AS LONG
        DIM InputData AS STRING
        DIM FileID AS LONG
        DIM InsideSection AS LONG
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        FUNCTION = %FALSE
        ON ERROR RESUME NEXT
        OPEN IniFIle FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF TRIM$(InputData) = "" THEN ITERATE DO
          IF ISFALSE(InsideSection) THEN
            IF UCASE$(InputData) = "[" & UCASE$(lSection) & "]" THEN
              InsideSection = %TRUE
            END IF
          ELSE
            IF ISTRUE(INI_LineIsSection(InputData)) THEN
              EXIT DO
            ELSE
              IF ISTRUE(INI_LineIsKey(InputData)) THEN
                IF LEFT$(InputData, LEN(lKey)) = lKey THEN
                  FUNCTION = %TRUE
                END IF
              END IF
            END IF
          END IF
        LOOP
        CLOSE #FileID
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Extract Section name without [ and ]
      ' Returns: a STRING containing the section name without [ and ]
      '---------------------------------------------------------------------------
      FUNCTION INI_SectionNameOnly(BYVAL lSection AS STRING) AS STRING
        FUNCTION = REMOVE$(TRIM$(lSection), ANY "[]")
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Extract Key name from a line
      ' Returns: a STRING with only the Key name
      '---------------------------------------------------------------------------
      FUNCTION INI_KeyNameOnly(BYVAL lLine AS STRING) AS STRING
        DIM Pos AS LONG          
        
        lLine = LTRIM$(lLine)
        Pos = INSTR(1,lLine,"=")
        IF Pos > 0 THEN
          FUNCTION = LEFT$(lLine, Pos - 1)
        END IF
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Get a Key value from an INI file
      ' Returns: a STRING with the value of lKey inside lSection
      '          if lKey is not found, lDefault value is returned
      '---------------------------------------------------------------------------
      FUNCTION INI_GetKey (BYVAL IniFile AS STRING, BYVAL lSection AS STRING, BYVAL lKey AS STRING, BYVAL lDefault AS STRING) AS STRING
        DIM zText AS ASCIIZ * 512
    
        GetPrivateProfileString BYCOPY lSection, BYCOPY lKey, BYCOPY lDefault, zText, SIZEOF(zText), BYCOPY IniFile
        FUNCTION = zText
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Set a Key value in an INI file
      '---------------------------------------------------------------------------
      FUNCTION INI_SetKey (BYVAL IniFile AS STRING, BYVAL lSection AS STRING, BYVAL lKey AS STRING, BYVAL Value AS STRING) AS LONG
        FUNCTION = WritePrivateProfileString(BYCOPY lSection, BYCOPY lKey, BYCOPY Value, BYCOPY IniFile)
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Delete an entire section and all it's keys from a given INI file
      '---------------------------------------------------------------------------
      FUNCTION INI_DeleteSection(BYVAL IniFile AS STRING, BYVAL lSection AS STRING) AS LONG
        FUNCTION = %FALSE
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        IF ISFALSE(INI_SectionExists(IniFile, lSection)) THEN
          EXIT FUNCTION
        END IF
        FUNCTION = WritePrivateProfileString(BYCOPY lSection, BYVAL %NULL, BYVAL %NULL, BYCOPY IniFile)
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Delete a key from a given INI file
      '---------------------------------------------------------------------------
      FUNCTION INI_DeleteKey(BYVAL IniFile AS STRING, BYVAL lSection AS STRING, BYVAL lKeyName AS STRING) AS LONG
        FUNCTION = %FALSE
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        FUNCTION = WritePrivateProfileString(BYCOPY lSection, BYCOPY lKeyName, BYVAL %NULL, BYCOPY IniFile)
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Delete a key's value from an INI file
      '---------------------------------------------------------------------------
      FUNCTION INI_DeleteKeyValue(BYVAL IniFile AS STRING, BYVAL lSection AS STRING, BYVAL lKeyName AS STRING) AS LONG
        FUNCTION = %FALSE
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        FUNCTION = WritePrivateProfileString(BYCOPY lSection, BYCOPY lKeyName, "", BYCOPY IniFile)
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Returns the total number of sections in a given INI file
      '---------------------------------------------------------------------------
      FUNCTION INI_GetTotalSections(BYVAL IniFile AS STRING) AS LONG
        DIM FileID AS LONG
        DIM Counter AS LONG
        DIM InputData AS STRING
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        ON ERROR RESUME NEXT
        FileID = FREEFILE
        OPEN IniFile FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF INI_LineIsSection(InputData) THEN Counter = Counter + 1
        LOOP
        CLOSE #FileID
        FUNCTION = Counter
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Returns the total number of keys in a given INI file
      '---------------------------------------------------------------------------
      FUNCTION INI_GetTotalKeys(BYVAL IniFile AS STRING) AS LONG
        DIM FileID AS LONG
        DIM Counter AS LONG
        DIM InputData AS STRING
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        ON ERROR RESUME NEXT
        FileID = FREEFILE
        OPEN IniFile FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF INI_LineIsKey(InputData) THEN INCR Counter
        LOOP
        CLOSE #FileID
        FUNCTION = Counter
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Returns the total number of keys in 1 given section.
      '---------------------------------------------------------------------------
      FUNCTION INI_GetSectionTotalKeys(BYVAL IniFile AS STRING, BYVAL lSection AS STRING) AS LONG
        DIM FileID AS LONG
        DIM InputData AS STRING
        DIM InsideSection AS LONG
        DIM NumKeys AS LONG
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        IF ISFALSE(INI_SectionExists(IniFile, lSection)) THEN EXIT FUNCTION
        InsideSection = %FALSE
        ON ERROR RESUME NEXT
        FileID = FREEFILE
        OPEN IniFile FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF TRIM$(InputData) = "" THEN ITERATE DO
          IF ISFALSE(InsideSection) THEN
            IF UCASE$(InputData) = "[" & UCASE$(lSection) & "]" THEN
              InsideSection = %TRUE
            END IF
          ELSE
            IF ISTRUE(INI_LineIsSection(InputData)) THEN
              EXIT DO
            ELSE
              IF ISTRUE(INI_LineIsKey(InputData)) THEN
                NumKeys = NumKeys + 1
              END IF
            END IF
          END IF
        LOOP
        CLOSE #FileID
        FUNCTION = NumKeys
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Get the list of all Sections inside a INI File
      ' Names separated by CRLF
      '---------------------------------------------------------------------------
      FUNCTION INI_GetSectionsList(BYVAL IniFile AS STRING) AS STRING
        DIM FileID AS LONG
        DIM Counter AS LONG
        DIM InputData AS STRING
        DIM tmpList AS STRING
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        ON ERROR RESUME NEXT
        FileID = FREEFILE
        OPEN IniFile FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF INI_LineIsSection(InputData) THEN
            InputData = INI_SectionNameOnly(InputData)
            INCR Counter
            IF Counter = 1 THEN
              tmpList = InputData
            ELSE
              tmpList = tmpList + $CRLF + InputData
            END IF
          END IF
        LOOP
        CLOSE #FileID
        FUNCTION = tmpList
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Get the Index of a Section inside a INI File
      '---------------------------------------------------------------------------
      FUNCTION INI_GetSectionIndex(BYVAL IniFile AS STRING, BYVAL lSection AS STRING) AS LONG
        DIM tmpList AS STRING
        DIM SectionName AS STRING
        DIM Count AS LONG
    
        tmpList = UCASE$(INI_GetSectionsList(IniFile))
        lSection = UCASE$(lSection)
        FOR Count = 1 TO PARSECOUNT(tmpList, $CRLF)
          IF PARSE$(tmpList, $CRLF, Count) = lSection THEN
            FUNCTION = Count
            EXIT FOR
          END IF
        NEXT Count
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Get the list of all Keys inside a Section
      ' Names separated by CRLF
      '---------------------------------------------------------------------------
      FUNCTION INI_GetSectionKeyList(BYVAL IniFile AS STRING, BYVAL lSection AS STRING) AS STRING
        DIM FileID AS LONG
        DIM InputData AS STRING
        DIM tmpList AS STRING
        DIM InsideSection AS LONG
        DIM Count AS LONG
    
        IF DIR$(IniFile) = "" THEN EXIT FUNCTION
        IF ISFALSE(INI_SectionExists(IniFile, lSection)) THEN EXIT FUNCTION
        InsideSection = %FALSE
        ON ERROR RESUME NEXT
        FileID = FREEFILE
        OPEN IniFile FOR INPUT AS #FileID
        DO WHILE NOT EOF(FileID)
          LINE INPUT #FileID, InputData
          IF TRIM$(InputData) = "" THEN ITERATE DO
          IF ISFALSE(InsideSection) THEN
            IF UCASE$(InputData) = "[" & UCASE$(lSection) & "]" THEN
              InsideSection = %TRUE
            END IF
          ELSE
            IF ISTRUE(INI_LineIsSection(InputData)) THEN
              EXIT DO
            ELSE
              IF ISTRUE(INI_LineIsKey(InputData)) THEN
                INCR Count
                InputData = INI_KeyNameOnly(InputData)
                IF Count = 1 THEN
                  tmpList = InputData
                ELSE
                  tmpList = tmpList + $CRLF + InputData
                END IF
              END IF
            END IF
          END IF
        LOOP
        CLOSE #FileID
        FUNCTION = tmpList
      END FUNCTION
    
      '---------------------------------------------------------------------------
      ' Get the Index of a Key inside a Section
      '---------------------------------------------------------------------------
      FUNCTION INI_GetSectionKeyIndex(BYVAL IniFile AS STRING, BYVAL lSection AS STRING, BYVAL lKey AS STRING) AS LONG
        DIM tmpList AS STRING
        DIM SectionName AS STRING
        DIM Count AS LONG
    
        tmpList = UCASE$(INI_GetSectionKeyList(IniFile, lSection))
        lKey = UCASE$(lKey)
        FOR Count = 1 TO PARSECOUNT(tmpList, $CRLF)
          IF PARSE$(tmpList, $CRLF, Count) = lKey THEN
            FUNCTION = Count
            EXIT FOR
          END IF
        NEXT Count
      END FUNCTION
    
    #ENDIF
    -Example program-------------------------------------------

    Code:
    #COMPILE EXE
    #REGISTER ALL
    $DIM ALL
    
      #INCLUDE "EOINI.inc"
    
      FUNCTION PBMAIN() AS LONG
        DIM IniFile AS STRING
        DIM nSections AS LONG
        DIM Count AS LONG
        DIM SectionList AS STRING
        DIM KeyList AS STRING
        DIM SectionName AS STRING
        DIM Message AS STRING
    
        IniFile = "TestIni.INI"
    
        Message = "You are looking inside INI file " + IniFile + $CRLF + _
                  "File contains:" + $CRLF + _
                  STR$(INI_GetTotalSections(IniFile)) + " sections" + $CRLF + _
                  STR$(INI_GetTotalKeys(IniFile)) + " keys" + $CRLF + _
                  ""
        MSGBOX Message
        
        'Create a CRLF separated list of all section names inside IniFile
        SectionList = INI_GetSectionsList(IniFile)
        
        'For each section inside IniFile, prints it's keys list
        FOR Count = 1 TO PARSECOUNT(SectionList,$CRLF)
            SectionName = PARSE$(SectionList,$CRLF,Count)
            KeyList = INI_GetSectionKeyList(IniFile, SectionName)
            Message = "Section name is: " + SectionName + $CRLF + _
                      "This section is section number : " + STR$(INI_GetSectionIndex(IniFile, SectionName)) + $CRLF + _
                      "Inside this section there are " + STR$(INI_GetSectionTotalKeys(IniFile, SectionName)) + " keys." + $CRLF + _
                      $CRLF + _
                      "Keys inside section are: " + $CRLF + _
                      $CRLF + _
                      KeyList
            MSGBOX Message
        NEXT Count
    
      END FUNCTION
    -Example INI File-------------------------------------------
    Name this file TestIni.INI

    Code:
    [Section 1]
    Key 2=Key2Value
    Key 3=Key3Value
    Key 4=Key4Value
    Key 5=Key5Value
    
    [Section 2]
    Key 1=Key1Value
    Key 2=Key2Value
    
    Key 3=Key3Value
    Key 4=Key4Value
    Key 5=Key5Value
    
    [Section 3]
    Key 1=Key1Value
    
    
    Key 2=Key2Value
    Key 3=Key3Value
    Key 4=Key4Value
    Key 5=Key5Value
    
    [Section 4]
    Key 1=Key1Value
    Key 2=Key2Value
    
    
    [Section 5]
    Key 1=Key1Value
    Key 2=Key2Value
    
    Key 3=Key3Value
    Key 4=Key4Value
    
    Key 5=Key5Value

    ------------------
    Eros Olmi
    mailto:[email protected][email protected]</A>

    [This message has been edited by Eros Olmi (edited July 12, 2002).]
    thinBasic programming language
    Win10 64bit - 8GB Ram - i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

  • #2
    I think there are two places where a line is missing:

    Code:
        ON ERROR RESUME NEXT
        OPEN IniFile FOR INPUT AS #FileID
    should be:

    Code:
        ON ERROR RESUME NEXT
        FileID = FREEFILE
        OPEN IniFile FOR INPUT AS #FileID


    ------------------

    Comment


    • #3
      Some background info:
      Code:
      '===============================================================================
      'Context:
      ' We're dealing with .ini files, which contain text lines ending in $CRLF.
      ' Only three types of text lines are permitted: Comment, Section begin, and Key.
      '
      ' A Section has a begin marker but no end marker.
      ' The beginning of the next Section implies the end of the previous Section.
      ' A Section begin marker line consists of a name enclosed in square brackets: [Settings]
      ' A Section marker line must begin with the [ and end with the ]. No chars before or after...
      ' Text lines that follow a Section begin marker line are considered to be "in" that Section, and
      '   can only be of either type: Comment or Key
      '
      ' A Comment is a line that begins with the char: ";"
      '
      ' A Key is a line that contains 3 elements: KeyName, "=", KeyValue
      '   eg:    ThisApp=C:\apps\myapp1\myapp1.exe
      '
      ' An .ini file may contain more than one Key having the same name, but only
      '   if they occur under different Sections:
      '   eg:   [Service]
      '         Color=red
      '         [Product]
      '         Color=green
      '
      '===============================================================================
          'WARNING: All API calls to Get/WritePrivateProfileString REQUIRE a FULL PATH
          '         or the call will fail!
      '===============================================================================

      ------------------

      Comment


      • #4
        this function lets you easily insert a section header without any keys, a comment, or a blank.
        -john


        Code:
        #include "eoini.inc"    'ini routines developed by eros olmi
                                'for code and more details about "eoini.inc", see:
                                '   http://www.powerbasic.com/support/pb...ad.php?t=25027    
        
        %before_section     = 1001
        %top_of_section     = 1002
        %bottom_of_section  = 1003
        
        $blank = " "    'better to use $spc or space$(1) etc...
        $comment = ";"  'at first i thought this required a space after, else the api kills the line. now not sure...
        '$other = "textline"   'not allowed unless preceeded with a ";"
        $other = "[newsection]"  ' yes, inserting just a section header is ok
        
        '===============================================  the reason for doing everything else in the file:
        function ini_setspecialline(byval inifullspec as string, byval txt as string, byval where as long, byval tgtsection as string) as long
            'this function supplements the ini_ functions; helps insert special types of lines into an ini file.
            '- a blank line
            '- a comment line
            '- a [section] line without any keys
        
            'note that "before a section" and "bottom of section" look alike, but are specified differently
        
            local filbuf as long, tmp as string, index as long, sleft, sright as string
        
            function = %true    'assume success unless an error arises
        
            filbuf& = freefile
            open inifullspec for binary as #filbuf&
            if err then
                function = %false
                exit function
            end if
            get$ #filbuf&, lof(filbuf&), tmp$
        
            index = instr(tmp$, tgtsection)     ' locate the section of interest!
            if index = 0 then
                function = %false
                exit function
            end if
        
            'divide the ini into sleft$ and sright$, using the index from above
            select case where
            case %before_section
                sleft$  = left$(tmp$, iif(index -2 >= 1, index-2, 0))
                sright$ = mid$(tmp$, index)
        
            case %top_of_section
                sleft$  = left$(tmp$, index + len(tgtsection))
                index   = instr(index, tmp$, $crlf)
                sright$ = mid$(tmp$, index+2)
        
            case %bottom_of_section
                index   = instr(index+1, tmp$, "[")' is actually start of next section; but looks/acts like %before_section
                sleft$  = left$(tmp$, index-1)
                sright$ = mid$(tmp$, index)
        
            end select
        
            'get set to write
            seek #filbuf&, 1
        
            'create the output according to what was requested
            select case txt
            case $blank
                put$ #filbuf&, sleft$ & $crlf & sright$
            case $comment
                'put$ #filbuf&, sleft$ & "; " & $crlf & sright$  ' barely a visible divider...
                put$ #filbuf&, sleft$ & ";"& string$(15, "-") & $crlf & sright$   'much better!
            case else   ' anything that's not a blank or a comment!
                if left$(txt,1) = "[" then   '
                    'section header with no keys
                    put$ #filbuf&, sleft$ &       txt & $crlf & sright$
                else
                    put$ #filbuf&, sleft$ & ";" & txt & $crlf & sright$   'these are allowed
                end if
            end select
            close #filbuf&
        end function
        ------------------

        Comment

        Working...
        X