Doppelte Einträge aus *.ini löschen

  • Hallo,

    wie bekommt man es hin das man doppelte Einträge in einer *.ini wieder löscht?
    Im Beispielscript trägt man per Tag ein ob man übernachtet hat oder nicht.
    Wenn man zB. am 01.12 versehentlich "Übernachtung" eingetragen hat und dies wieder ändern möchten in "keine Übernachtung"
    muss zum einen der Eintrag "Übernachtung" in der *.ini gelöscht werden bei "keine Übernachtung" wieder eingetragen werden.
    Das ganze soll dann auch noch korrekt in den Inputs angezeigt werden.

    Beispiel:

    Spoiler anzeigen
    [autoit]

    #include <ButtonConstants.au3>
    #include <DateTimeConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    Opt("GUIOnEventMode", 1)
    #Region ### START Koda GUI section ### Form=
    Global $Form1 = GUICreate("Form1", 219, 438, 543, 159)
    Global $Input1 = GUICtrlCreateInput("0", 48, 272, 121, 21)
    Global $Input2 = GUICtrlCreateInput("0", 48, 328, 121, 21)
    $Label1 = GUICtrlCreateLabel("Übernachtungen", 64, 248, 84, 17)
    $Label2 = GUICtrlCreateLabel("Keine Übernachtungen", 56, 304, 114, 17)
    Global $Button1 = GUICtrlCreateButton("Eintragen", 72, 360, 75, 25)
    Global $Button2 = GUICtrlCreateButton("Beenden", 136, 408, 75, 25)
    Global $MonthCal1 = GUICtrlCreateMonthCal("2014/12/28", 16, 8, 191, 164)
    $Group1 = GUICtrlCreateGroup("Übernachtung", 48, 184, 129, 57)
    Global $Radio1 = GUICtrlCreateRadio("Ja", 65, 210, 49, 17)
    Global $Radio2 = GUICtrlCreateRadio("Nein", 120, 209, 49, 17)
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlSetState($Radio1, $GUI_CHECKED)

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlSetOnEvent($Button1, "lesen_schreiben")
    GUICtrlSetOnEvent($Button2, "Ende")
    GUISetOnEvent($GUI_EVENT_CLOSE, "Ende")

    [/autoit] [autoit][/autoit] [autoit]

    Func Lesen_Schreiben()
    $kalender_lesen = GUICtrlRead($MonthCal1)
    $uebernachtungen = GUICtrlRead($Input1)
    $keine_uebernachtungen = GUICtrlRead($Input2)

    [/autoit] [autoit][/autoit] [autoit]

    If BitAND(GUICtrlRead($Radio1), $GUI_CHECKED) = $GUI_CHECKED Then
    IniWrite(@ScriptDir & '\test.ini', 'Übernachtung', $kalender_lesen, '1')
    GUICtrlSetData($Input1, $uebernachtungen +1)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If BitAND(GUICtrlRead($Radio2), $GUI_CHECKED) = $GUI_CHECKED Then
    IniWrite(@ScriptDir & '\test.ini', 'Keine Übernachtung', $kalender_lesen, '1')
    GUICtrlSetData($Input2, $keine_uebernachtungen +1)
    EndIf
    EndFunc;==>lesen_schreiben

    [/autoit] [autoit][/autoit] [autoit]

    Func Ende()
    Exit
    EndFunc;==>Ende

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(100)
    WEnd

    [/autoit]


    Hatte schon versucht das über Arrays zu machen, da bin ich aber immer dran gescheitert das diese bei Monatsanfang leer sind und
    das Script zum absturz brachten.
    zB so:

    [autoit]

    Local $uebernachtungen_vergleich = IniReadSection(@ScriptDir & '\test.ini', 'Hotel')
    $suche_doppelt_eintrag = _ArraySearch($uebernachtungen_vergleich, $kalender_lesen)

    [/autoit]

    Hoffe mal mich nicht zu umständlich ausgedrückt zu haben.

    Das ganze ist nur ein sehr kleiner Teil eines größeren Scriptes, das ich hier aber nicht Posten kann/darf da dort realdaten stehen.
    Schaut so aus:
    autoit.de/wcf/attachment/25025/


    Gruss
    oh-ha-2

  • [autoit]

    #include <File.au3>
    #include <Array.au3>
    Local $aArray, $sPath = @ScriptDir & "\Test.ini"
    _FileReadToArray($sPath, $aArray)
    $aArray = _ArrayUnique($aArray, 1, 1)
    _FileWriteFromArray($sPath, $aArray, 1)

    [/autoit]
    Spoiler anzeigen
    [autoit]

    ;~ #include <File.au3>
    ;~ #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Local $aArray, $sPath = @ScriptDir & "\Test.ini"
    _FileReadToArray($sPath, $aArray)
    $aArray = _ArrayUnique($aArray, 1, 1)
    _FileWriteFromArray($sPath, $aArray, 1)

    [/autoit] [autoit][/autoit] [autoit]

    Func _FileReadToArray($sFilePath, ByRef $aArray, $iFlag = 1)
    If $iFlag Or $iFlag = Default Then
    Local $hFileOpen = FileOpen($sFilePath, 0)
    If $hFileOpen = -1 Then Return SetError(1, 0, 0)
    Local $sFileRead = FileRead($hFileOpen)
    FileClose($hFileOpen)

    [/autoit] [autoit][/autoit] [autoit]

    If StringLen($sFileRead) Then
    $aArray = StringRegExp(@CRLF & $sFileRead, "([^\r\n]*)(?:\r\n|\n|\r|$)", 3)
    $aArray[0] = UBound($aArray) - 2
    ReDim $aArray[UBound($aArray) - 1]
    Else
    Return SetError(2, 0, 0)
    EndIf
    Else
    $aArray = FileReadToArray($sFilePath)
    If @error Then Return SetError(@error, 0, 0)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Return 1
    EndFunc ;==>_FileReadToArray

    [/autoit] [autoit][/autoit] [autoit]

    Func _FileWriteFromArray($sFilePath, Const ByRef $aArray, $iBase = Default, $iUBound = Default, $sDelimeter = "|")
    ; Check if we have a valid array as input
    If Not IsArray($aArray) Then Return SetError(2, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    ; Check the number of dimensions
    Local $iDims = UBound($aArray, 0)
    If $iDims > 2 Then Return SetError(4, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    ; Determine last entry of the array
    Local $iLast = UBound($aArray) - 1
    If $iUBound = Default Or $iUBound > $iLast Then $iUBound = $iLast
    If $iBase < 0 Or $iBase = Default Then $iBase = 0
    If $iBase > $iUBound Then Return SetError(5, 0, 0)
    If $sDelimeter = Default Then $sDelimeter = "|"

    [/autoit] [autoit][/autoit] [autoit]

    ; Open output file for overwrite by default, or use input file handle if passed
    Local $hFileOpen = $sFilePath
    If IsString($sFilePath) Then
    $hFileOpen = FileOpen($sFilePath, 2)
    EndIf
    If $hFileOpen = -1 Then Return SetError(1, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    ; Write array data to file
    Local $iError = 0
    Switch $iDims
    Case 1
    For $i = $iBase To $iUBound
    If FileWrite($hFileOpen, $aArray[$i] & @CRLF) = 0 Then
    $iError = 3
    ExitLoop
    EndIf
    Next
    Case 2
    Local $sTemp
    Local $iCols = UBound($aArray, 2)
    For $i = $iBase To $iUBound
    $sTemp = $aArray[$i][0]
    For $j = 1 To $iCols - 1
    $sTemp &= $sDelimeter & $aArray[$i][$j]
    Next
    If FileWrite($hFileOpen, $sTemp & @CRLF) = 0 Then
    $iError = 3
    ExitLoop
    EndIf
    Next
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    ; Close file only if specified by a string path
    If IsString($sFilePath) Then FileClose($hFileOpen)

    [/autoit] [autoit][/autoit] [autoit]

    ; Return results
    If $iError Then Return SetError($iError, 0, 0)
    Return 1
    EndFunc ;==>_FileWriteFromArray

    [/autoit] [autoit][/autoit] [autoit]

    Func _ArrayUnique(Const ByRef $aArray, $iColumn = Default, $iBase = Default, $iCase = Default, $iFlags = Default)
    If $iColumn = Default Then $iColumn = 1
    If $iBase = Default Then $iBase = 0
    If $iCase = Default Then $iCase = 0
    If $iFlags = Default Then $iFlags = 1
    ; Start bounds checking
    If UBound($aArray) = 0 Then Return SetError(1, 0, 0) ; Check if array is empty, or not an array
    ; $iBase can only be 0 or 1, if anything else, return with an error
    If $iBase < 0 Or $iBase > 1 Or (Not IsInt($iBase)) Then Return SetError(2, 0, 0)
    If $iCase < 0 Or $iCase > 1 Or (Not IsInt($iCase)) Then Return SetError(2, 0, 0)
    If $iFlags < 0 Or $iFlags > 1 Or (Not IsInt($iFlags)) Then Return SetError(4, 0, 0)
    Local $iDims = UBound($aArray, 0), $iNumColumns = UBound($aArray, 2)
    If $iDims > 2 Then Return SetError(3, 0, 0)
    ; checks the given dimension is valid
    If ($iColumn < 1) Or ($iNumColumns = 0 And ($iColumn - 1 > $iNumColumns)) Or ($iNumColumns > 0 And ($iColumn > $iNumColumns)) Then Return SetError(3, 0, 0)
    ; make $iColumn an array index, note this is ignored for 1D arrays
    $iColumn -= 1
    ; create dictionary
    Local $oD = ObjCreate("Scripting.Dictionary")
    ; compare mode for strings
    ; 0 = binary, which is case sensitive
    ; 1 = text, which is case insensitive
    ; this expression forces either 1 or 0
    $oD.CompareMode = Number(Not $iCase)
    Local $vElem
    ; walk the input array
    For $i = $iBase To UBound($aArray) - 1
    If $iDims = 1 Then
    ; 1D array
    $vElem = $aArray[$i]
    Else
    ; 2D array
    $vElem = $aArray[$i][$iColumn]
    EndIf
    ; add key to dictionary
    ; NOTE: accessing the value (.Item property) of a key that doesn't exist creates the key :)
    ; keys are guaranteed to be unique
    $oD.Item($vElem)
    Next
    ;
    ; return the array of unique keys
    If BitAND($iFlags, 1) = 1 Then
    Local $aTemp = $oD.Keys()
    _ArrayInsert($aTemp, 0, $oD.Count)
    Return $aTemp
    Else
    Return $oD.Keys()
    EndIf
    EndFunc ;==>_ArrayUnique

    [/autoit] [autoit][/autoit] [autoit]

    Func _ArrayInsert(ByRef $avArray, $iElement, $vValue = "")
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    ; Check element in array bounds + 1
    If $iElement > UBound($avArray) Then Return SetError(3, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    ; Add 1 to the array
    Local $iUBound = UBound($avArray) + 1
    ReDim $avArray[$iUBound]

    [/autoit] [autoit][/autoit] [autoit]

    ; Move all entries over til the specified element
    For $i = $iUBound - 1 To $iElement + 1 Step -1
    $avArray[$i] = $avArray[$i - 1]
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; Add the value in the specified element
    $avArray[$iElement] = $vValue
    Return $iUBound
    EndFunc ;==>_ArrayInsert

    [/autoit]

    Einmal editiert, zuletzt von blackcho (28. Dezember 2014 um 14:09)

  • Hmmm,

    habe ich mich wohl falsch ausgedrückt oder verstehe nicht was du mir damit sagen möchtest.
    Die ini in ein Array einlesen ist nicht das Problem das ich habe. Ich möchte halt nur den
    Eintrag aus der einen Sektion [Übernachtung] weghaben und und in der anderen Sektion [Keine Übernachtung] eintragen und andersherum.
    Des weiteren dann halt auch die Inputs endsprechend aktualisieren wie sie halt in der ini stehen.

    Gruss
    oh-ha-2

  • Der doppelte Eintrag kommt ja automatisch wenn man eine falsche Eingabe berichtigen möchte.
    Wie ich den aus der Sektion löschen kann weiss ich, nur bekomme ich es nicht zum laufen den zum einen zu löschen plus die
    Inputs dementsprechend anzupassen. Quasi beides zusammen macht mir kopfzerbrechen.


    Gruss
    oh-ha-2

    • Offizieller Beitrag

    Einach den Eintrag in der Ini mit IniDelete löschen und den entsprechenden Radio mittels GUICtrlSetState setzen.

    [autoit]

    IniDelete(@ScriptDir & '\test.ini', 'Übernachtung', $kalender_lesen)
    IniWrite(@ScriptDir & '\test.ini', 'Keine Übernachtung', $kalender_lesen, '1')

    [/autoit]


    Beispiel für Radiobutton1:

    [autoit]

    GUICtrlSetState($Radio1,$GUI_CHECKED)

    [/autoit]
  • Ups,

    Nü komme selbst ich durcheinander ?( . Habe ich das oben denn so schlecht erklärt?
    Wie man an Radios/Checkboxen einen Haken macht weiss ich und auch wie man den weg bekommt.
    War aber auch nicht gefragt.
    Wie man in den einzelnen Sektionen etwas reinschreibt oder löscht weiss ich auch.
    Nur das zusammenspiel Löschen, reinschreiben plus die beiden Inputs entsprechend anpassen da hakt es bei mir.

    Anhand meines Beispielskrips,Post1, noch mal erklärt, hoffe mal das ich es jetzt besser mache.
    Inhalt der Test.ini

    Code
    [Übernachtung]
    2014/12/01=1
    2014/12/02=1
    2014/12/03=1
    2014/12/04=1
    [Keine Übernachtung]
    2014/12/05=1
    2014/12/06=1
    2014/12/07=1

    Anzeige $Input1 = 4
    Anzeige $Input2 = 3
    Wenn man nun im Kalender zB den 02.12.2014 anklickt und das Radio2=keine Übernachtung Checkt dann soll zum einen in der Test.ini
    bei Übernachtung der Eintrag 2014/12/02=1 raus und bei keine Übernachtung der Eintrag 2014/12/02=1 rein.
    Desweiteren müssen dann ja auch die beiden Inputs angepasst werden.
    Das ganze müßte dann so aussehen in der Test.ini.

    Code
    [Übernachtung]
    2014/12/01=1
    2014/12/03=1
    2014/12/04=1
    [Keine Übernachtung]
    2014/12/05=1
    2014/12/06=1
    2014/12/07=1
    2014/12/02=1


    Anzeige $Input1 = 3
    Anzeige $Input2 = 4

    Gruss
    oh-ha-2

    Einmal editiert, zuletzt von oh-ha-2 (28. Dezember 2014 um 15:06)

    • Offizieller Beitrag

    Mal unabhängig von deinem Problem, deine Programmlogik ist wenig sinnvoll.
    Warum schreibst du verschiedene Sektionen für Übernachtung/keine Übernachtung ?
    Datum=1 ; Das ist Übernachtung
    Datum=0 ; Das ist dann keine Übernachtung
    So ist alles in einer Sektion und leicht zu handhaben.

    Noch sinnvoller wäre eigentlich, dafür SQLite zu verwenden. Hier laufen doch nach und nach einige Daten auf, da ist eine Datenbank die bessere Lösung.

  • Hallo BugFix,


    kommt in Wirklichkeit noch eine Sektion dabei und auch bei 2014/12/01=1 kann es eine =2 oder =3 sein.
    Wollte das Beispiel halt nicht so aufblähen. Mir wäre ja schon geholfen gewesen das eine Problem zu lösen.

    Mit SQLite kenne ich mich null aus, werde es mir aber mal anschauen müssen für andere Projekte.
    Dieses Kalendarium hat alleine schon 4 Ini Dateien. Um das noch alles zu ändern müßte ich alles neu schreiben.
    Ist bis dato auch schon lauffähig bis auf ein paar kleine sachen.


    Gruss
    oh-ha-2

    • Offizieller Beitrag

    Mir wäre ja schon geholfen gewesen das eine Problem zu lösen.


    Also Raupis Vorschlag löst genau dein Problem.
    Der Eintrag aus Übernachtung wird gelöscht und in keine Übernachtung eingetragen.
    Anschließend setzt du den Radio-Button zur Korrektur.

  • ein thema das echt gut ist !!!

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

  • Ich gebe es auf.
    Werde schon dahinter kommen wie man die Anzahl in den Inputs anpasst zu den Einträgen in der Ini.
    Keine Ahnung warum hier auf den beiden Radios rumgeritten wird. Die waren nie das Problem, hätte wohl besser Zwei Buttons machen sollen im Beispielskript.
    einer mit "Übernachtung" und einer mit "keiner Übernachtung".


    Gruss
    oh-ha-2

    • Offizieller Beitrag

    Wenn du Zählen willst, wie viele Tage in Übernachtung/keine Übernachtung sind benutze einfach IniReadSection.
    Im Element [0][0] steht die Anzahl der Einträge. Frage ist jetzt nur, willst du alle Tage im Input anzeigen, oder soll das dann Monatsweise sein?
    Ich denke für deine Daten ist eine Ini suboptimal.

  • Hatte schon versucht das über Arrays zu machen, da bin ich aber immer dran gescheitert das diese bei Monatsanfang leer sind und
    das Script zum absturz brachten.

    Wenn du mit dieser Variante zum Erfolg kommen kannst, dann versuch doch einfach, diesen Absturz zu umgehen/verhindern indem du, sobald du das Array verwenden willst, einfach prüfst, ob es auch tatsächlich ein Array ist. Schau dir mal in der Hilfe den Befehl " IsArray " näher an. Dann würde ich mit If-Else weitermachen.

  • Danke Lottich,

    IsArray, das war genau das was mir fehlte, kannte ich nicht und stand auch nicht in der Hilfe bei den Arrays.
    Muss dabei sagen das ich Arrays in der Vergangenheit gemieden hatte wie die Pest, dank BugFix aber inzwischen recht gut damit klar kam, dachte ich zumindest.
    Habe es nun, dank deiner Hilfe, so gelöst:

    Spoiler anzeigen
    [autoit]

    #include <ButtonConstants.au3>
    #include <DateTimeConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    #Region ### START Koda GUI section ### Form=
    Global $Form1 = GUICreate("Form1", 219, 438, 543, 159)
    Global $Input1 = GUICtrlCreateInput("0", 48, 272, 121, 21)
    Global $Input2 = GUICtrlCreateInput("0", 48, 328, 121, 21)
    $Label1 = GUICtrlCreateLabel("Übernachtungen", 64, 248, 84, 17)
    $Label2 = GUICtrlCreateLabel("Keine Übernachtungen", 56, 304, 114, 17)
    Global $Button1 = GUICtrlCreateButton("Eintragen", 72, 360, 75, 25)
    Global $Button2 = GUICtrlCreateButton("Beenden", 136, 408, 75, 25)
    Global $MonthCal1 = GUICtrlCreateMonthCal("2014/12/28", 16, 8, 191, 164)
    $Group1 = GUICtrlCreateGroup("Übernachtung", 48, 184, 129, 57)
    Global $Radio1 = GUICtrlCreateRadio("Ja", 65, 210, 49, 17)
    Global $Radio2 = GUICtrlCreateRadio("Nein", 120, 209, 49, 17)
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlSetState($Radio1, $GUI_CHECKED)
    GUICtrlSetOnEvent($Button1, "lesen_schreiben")
    GUICtrlSetOnEvent($Button2, "Ende")
    GUISetOnEvent($GUI_EVENT_CLOSE, "Ende")

    [/autoit] [autoit][/autoit] [autoit]

    Func Lesen_Schreiben()
    $kalender_lesen = GUICtrlRead($MonthCal1)
    $uebernachtungen = GUICtrlRead($Input1)
    $keine_uebernachtungen = GUICtrlRead($Input2)

    [/autoit] [autoit][/autoit] [autoit]

    If BitAND(GUICtrlRead($Radio1), $GUI_CHECKED) = $GUI_CHECKED Then
    IniWrite(@ScriptDir & '\test.ini', 'Übernachtung', $kalender_lesen, '1')
    Local $uebernachtungen_vergleich_uebernachtung = IniReadSection(@ScriptDir & '\test.ini', 'Übernachtung')
    IniDelete(@ScriptDir & '\test.ini', 'Keine Übernachtung', $kalender_lesen)
    If IsArray($uebernachtungen_vergleich_uebernachtung) Then
    GUICtrlSetData($Input1, $uebernachtungen_vergleich_uebernachtung[0][0])
    Local $uebernachtungen_vergleich_keine = IniReadSection(@ScriptDir & '\test.ini', 'Keine Übernachtung')
    If IsArray($uebernachtungen_vergleich_keine) Then
    GUICtrlSetData($Input2, $uebernachtungen_vergleich_keine[0][0])
    EndIf
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If BitAND(GUICtrlRead($Radio2), $GUI_CHECKED) = $GUI_CHECKED Then
    IniWrite(@ScriptDir & '\test.ini', 'Keine Übernachtung', $kalender_lesen, '1')
    Local $uebernachtungen_vergleich_keine = IniReadSection(@ScriptDir & '\test.ini', 'Keine Übernachtung')
    IniDelete(@ScriptDir & '\test.ini', 'Übernachtung', $kalender_lesen)
    If IsArray($uebernachtungen_vergleich_keine) Then
    GUICtrlSetData($Input2, $uebernachtungen_vergleich_keine[0][0])
    Local $uebernachtungen_vergleich_uebernachtung = IniReadSection(@ScriptDir & '\test.ini', 'Übernachtung')
    If IsArray($uebernachtungen_vergleich_uebernachtung) Then
    GUICtrlSetData($Input1, $uebernachtungen_vergleich_uebernachtung[0][0])
    EndIf
    EndIf
    EndIf
    EndFunc;==>lesen_schreiben

    [/autoit] [autoit][/autoit] [autoit]

    Func Ende()
    Exit
    EndFunc;==>Ende

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(100)
    WEnd

    [/autoit]

    Ich denke für deine Daten ist eine Ini suboptimal.


    Da muss ich dir und auch BugFix recht geben. Werde ich mir in jeden Fall mal anschauen mit dem SQLite, nur für dieses Kalendarium bringt es mir jetzt nichts mehr. Ist fast fertig überarbeitet.

    So und nun mache ich etwas das ich wohl offensichtlich besser kann als hier eine verständliche Frage zu stellen. Baue meiner Tochter einen Schrank zusammen.

    Gruss und guten Rutsch ins neue Jahr
    oh-ha-2