FileWrite zu langsam. Fast 2 Minuten!!!!

  • Hallo Zusammen!

    Ich habe ein Problem mit der Geschwindigkeit meines Programms. Zuerst einmal muss ich sagen, dass es eigentlich sonst einwandfrei klappt... Nur braucht es zum beschreiben eines Files fast 2 Minuten. Es sind zwar über 900 Zeilen... Aber bevor ich ein Paar nötige Änderungen vorgenommen habe, war es in null-komma-nix fertig.

    Jedenfalls hier die kurze Vorgeschichte/Erklärung zum Programm:

    Ich hab ne GUI, in die eine Exceldatei eingebettet ist, an der man Änderungen vornehmen kann. Nachdem man das gemacht hat wird die Exceldatei über ein Excel-Makro als .csv Datei gespeichert. Diese .csv-Datei wird wiederum von meinem Autoit-Skript in einem Array (_FileReadToArray()) gespeichert, aus dem einzelne Werte gelesen werden und dann in eine Textdatei geschrieben werden, die als .eep-Datei abgespeichert wird.

    Diese Textdatei habe ich anfangs einfach nur mit "FileOpen()" kreiert. So wurde sie dann einfach dort abgespeichert, wo meine ursprüngliche Exceldatei herkommt. Jetzt ist es aber so, dass ich die .eep-Datei an einem vom User gewählten Speicherort mit einem vom User gewählten Dateiname speichern soll.

    Eigentlich wollte ich das mit einem FileSaveDialog() machen, aber da wird mein Speicherort nicht übernommen.

    Ich hab jetzt ein Programm, dass den Namen UND den Ort auswählen lässt UND welches auch funktioniert... aber es braucht halt für die FileWrite-Sache ca 2 Minuten.

    Hier ist mal die Funktion aus meinem Skript in der sich das ganze abspielt.

    Spoiler anzeigen
    [autoit]

    Func CreateButtonClicked() ;Function which defines what happens when the "Create EEP file" button is clicked
    MouseClick ( "", 300, 300, 1) ;activates Excel Sheet, so the macros can be played
    $UserInput = GUICtrlRead($UserNameInput) ;input field for user name is read
    ; $EEPInput = GUICtrlRead($EEPNameInput) ;input field for EEP-file name is read
    $Comment = GUICtrlRead($CommentInput) ;input field for comment is read
    ; Asks the user to enter a password. Don't forget to validate it!
    Local $EEPInput = InputBox("Filename", "Pick a name for your EEP File", "")

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

    If $EEPInput == "" Then ;routine that ensures that the EEP file gets a name
    MsgBox(0,"","you have to give your EEP file a name!")
    Else
    $oExcelDoc.Application.Run("SaveAsCsv") ;if the EEP file got a name, a csv file is created
    $zielpfad = FileSelectFolder("Choose the destination", "", 3, @ScriptDir)

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

    ;$var = FileSaveDialog("Choose name and destination for EEP file", "", "EEP file (*.eep)", "createdEEP")
    If StringRight($EEPInput, 4) <> ".eep" Then $EEPInput &= ".eep"
    ;$var.save
    ;Local $file = FileOpen($EEPInput, 1) ;a textfile with the chosen EEP-file name is created with the ending .eep
    local $file = $zielpfad & "" & $EEPInput
    Local $fileCreate = _FileCreate($file)
    ;Local $file = FileOpen($EEPInput & ".eep", 1) ;a textfile with the chosen EEP-file name is created with the ending .eep
    _FileReadToArray(@TEMPdir & "\Test.csv", $array) ;created csv file is saved in an array
    ;insert header in .eep file
    FileWrite($file, "################################################################################" & @CRLF)
    FileWrite($file, "#Created with Excel to EEP programme" & @CRLF)
    FileWrite($file, "#User: " & $UserInput & " Date: " & @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF)
    FileWrite($file, "#Project File: " & $EEPInput & @CRLF)
    FileWrite($file, "#Remarks: " & $Comment & @CRLF)
    FileWrite($file, "################################################################################" & @CRLF)
    FileWrite($file, @CRLF)
    For $zeile = 13 To $array[0] ;array is being worked with
    $wert = StringSplit($array[$zeile], ";") ;values in between semicolons are being separated and
    $number = number($wert[1]) ;values of first collumn of array are converted into a number

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

    Local $Zahl1 = 4096 ;this number is being calculated,
    Local $Zahl2 = 256 ;so that a hex number with 4 characters develops
    Local $Zahl3 = 16 ;this is done with the array which was defined at the top of the programm
    $Ziffer1 = Int($number/$Zahl1) ;(from 0 to F)
    $Rest1 = Mod($number,$Zahl1)
    $Ziffer2 = Int($Rest1/$Zahl2)
    $Rest2 = Mod($Rest1,$Zahl2)
    $Ziffer3 = Int($Rest2/$Zahl3)
    $Ziffer4 = Mod($Rest2,$Zahl3)
    Local $ArrString = $arr[$Ziffer1] & $arr[$Ziffer2] & $arr[$Ziffer3] & $arr[$Ziffer4] ;4 digit hex number (calculated above) is put together

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

    if $ArrString <> "0000" then ;for all the other parameters
    $summe = $summe + $wert[6]
    $value = $wert[6]
    $modulo = mod($summe, 256)
    $intwert = int($summe/256) -1
    Endif
    Next
    For $zeile = 1 To $array[0] ;array is being worked with
    $wert = StringSplit($array[$zeile], ";") ;values in between semicolons are being separated and written into $wert

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

    $number = number($wert[1]) ;values of first collumn of array are converted into a number

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

    Local $Zahl1 = 4096 ;this number is being calculated,
    Local $Zahl2 = 256 ;so that a hex number with 4 characters develops
    Local $Zahl3 = 16 ;this is done with the array which was defined at the top of the programm
    $Ziffer1 = Int($number/$Zahl1) ;(from 0 to F)
    $Rest1 = Mod($number,$Zahl1)
    $Ziffer2 = Int($Rest1/$Zahl2)
    $Rest2 = Mod($Rest1,$Zahl2)
    $Ziffer3 = Int($Rest2/$Zahl3)
    $Ziffer4 = Mod($Rest2,$Zahl3)
    Local $ArrString = $arr[$Ziffer1] & $arr[$Ziffer2] & $arr[$Ziffer3] & $arr[$Ziffer4] ;4 digit hex number (calculated above) is put together

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

    if $wert[2] == "CalculateCRC" then ;first line has to be read separately,
    FileWrite($file, hex($wert[1],4)) ;because its adress is "0"
    FileWrite($file, " " & hex($wert[6],2) & ";") ;and many other non relevant parameters have this adress too
    FileWrite($file, " " & $wert[5] & ";") ;...so the line for the first parameter is done seperately
    FileWrite($file, " " & $wert[4] & @CRLF) ;in this if-statement
    elseif $ArrString == "0006" then
    FileWrite($file, hex($wert[1],4)) ;because this is the checksum
    FileWrite($file, " " & hex($intwert,2) & ";") ;it has to be calculated differently
    FileWrite($file, " " & "Checksum" & ";") ;...so it is done seperately
    FileWrite($file, " " & "Checksum" & @CRLF) ;in this if-statement

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

    elseif $ArrString == "0007" then
    FileWrite($file, hex($wert[1],4)) ;because this is the checksum
    FileWrite($file, " " & hex(int($modulo),2) & ";") ;it has to be calculated differently
    FileWrite($file, " " & "Checksum" & ";") ;...so it is done seperately
    FileWrite($file, " " & "Checksum" & @CRLF) ;in this if-statement
    elseif $ArrString <> "0000" then ;for all the other parameters
    FileWrite($file, $arr[$Ziffer1] & $arr[$Ziffer2] & $arr[$Ziffer3] & $arr[$Ziffer4]) ;this if statement creates the lines
    FileWrite($file, " " & hex($wert[6],2) & ";") ;in the .eep file
    FileWrite($file, " " & $wert[5] & ";")
    FileWrite($file, " " & $wert[4] & @CRLF)
    EndIf
    Next
    MsgBox(0,"","You can find the EEP file where the used Excel file is located!") ;Messagebox to show the routine is done and to show where the .eep file is saved
    EndIf
    $oExcelDoc.Application.Run("myFolder")
    GUIRegisterMsg($WM_PAINT, "WM_PAINT")

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

    EndFunc

    [/autoit]

    Könnt ihr mir bitte helfen?

    Vlt kann mir einer von euch sagen, warum mein FileSaveDialog den ausgewählten Speicherort nicht übernimmt?

    Oder wie ich den oben gezeigten Code ein Bisschen beschleunigen kann?

    Das wäre super toll!

    Einmal editiert, zuletzt von vakaba (12. Februar 2014 um 14:12)

  • Warum verwendest Du das FileOpen nicht mehr?
    Jetzt wird für jeden Schreibbefehl die Datei geöffnet, ein paar Byte geschrieben und die Datei wieder geschlossen. Das dauert ...

  • Danke für den Tipp...

    Aber könntest du mir sagen, wo ich den FileOpen()-Befehl verwenden muss?

    Einfach das _FileCreate() in Zeile 20 damit zu erstetzen hilft leider geschwindigkeitstechnisch nicht.

    Kann ich den FileOpen Befehl verwenden und dem Befehl irgendwie vorgeben wo gespeichert werden muss?

  • Diesen ganzen Block

    [autoit]

    ;Local $file = FileOpen($EEPInput, 1) ;a textfile with the chosen EEP-file name is created with the ending .eep
    Local $file = $zielpfad & "" & $EEPInput
    Local $fileCreate = _FileCreate($file)
    ;Local $file = FileOpen($EEPInput & ".eep", 1) ;a textfile with the chosen EEP-file name is created with the ending .eep

    [/autoit]

    würde ich ersetzen druch

    [autoit]

    Local $file = FileOpen($EEPInput, 1) ;a textfile with the chosen EEP-file name is created with the ending .eep

    [/autoit]


    Am Ende des Skripts gehört dann noch ein FileClose($file) eingefügt.

  • Wenn es noch schneller gehen muss, dann schreib zuerst alles in eine einzige Variable und schreib diese dann mit einem einzigen FileWrite in die Datei.

  • Ja du hast schon Recht, jetzt ist es auf jeden Fall VIIIEEEEL schneller!!! :)

    ABER... jetzt kann ich wieder nicht bestimmen wo $file abgespeichert werden soll. Das wird jetzt einfach da abgespeichert, wo meine ursprüngliche Excel Datei her ist. Aber ich will den User wählen lassen. Am aller liebsten auch über nen FileSaveDialog, weil dort Name und Speicherort ausgewählt werden kann. Aber ich bekomme es nicht hin den ausgewählten Speicherort zu übernehmen... :(

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

    Edit: Nein jetzt ist es schnell genug... das mit in eine Variable schreiben brauche ich glaub nicht mehr. Jetzt fehlt nur noch das Speicherplatz angeben...

  • Dann bitte anpassen auf:

    [autoit]

    Local $file = FileOpen($zielpfad & $EEPInput, 1) ;a textfile with the chosen EEP-file name is created with the ending .eep

    [/autoit]
  • Super gut! Danke water!!!

    Wieder mal bist du mein Retter in der Not!!! :)

    Da bei meinem $zielpfad hinten kein "\" dran ist, musste ich zwischen die zwei Variablen noch & "\" & einsetzen. Aber jetzt klappt es super! :)

    Jetzt versuche ich noch das ganze mit einem FileSaveDialog hinzubekommen. Aber da es jetzt funktioniert, ist dieses Thema nun geschlossen :)

  • :)
    Stimmt. ich habe mich gefragt warum da ein

    [autoit]

    & "" &

    [/autoit]

    zusätzlich drin war. Aber das ist die Forensoftware die den Backslash rausgeworfen hat.

  • Das Problem ist zwar schon gelöst aber ich hab es jetzt auch mit dem SaveDialog hinbekommen, was schöner ist als Name und Speicherort getrennt abzufragen. Jetzt wo ich es geschafft habe, verstehe ich nicht, warum ich das vorhin nicht hinbekommen habe... :D

    [autoit]


    $var = FileSaveDialog("Choose name and destination for EEP file", "", "EEP file (*.eep)", "createdEEP")
    If StringRight($var, 4) <> ".eep" Then $var &= ".eep"
    MsgBox(0,"",$var)
    Local $file = FileOpen($var, 1) ;a textfile with the chosen EEP-file name is created with the ending .eep

    [/autoit][autoit][/autoit][autoit][/autoit]
  • Hi!
    Die zu schreibenden Werte sammeln und dann mit einem Funktionsaufruf schreiben! ;)

    Spoiler anzeigen
    [autoit]


    Local $file = FileOpen("test.txt", 1)
    FileWrite($file, "################################################################################" & @CRLF)
    FileWrite($file, "#Created with Excel to EEP programme" & @CRLF)
    FileWrite($file, "#User: " & 'XXXXX' & " Date: " & @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF)
    FileWrite($file, "#Project File: " & 'YYYYYY' & @CRLF)
    FileWrite($file, "#Remarks: " & 'ZZZZZZ' & @CRLF)
    FileWrite($file, "################################################################################" & @CRLF)
    FileWrite($file, @CRLF)
    FileClose($file)

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

    ; Besser:
    ; Die zu schreibenden Werte sammeln und dann mit einem Funktionsaufruf schreiben!
    Local $sToWrite = ''
    $sToWrite &= @CRLF
    $sToWrite &= "#################################################################################" & @CRLF
    $sToWrite &= "#Die zu schreibenden Werte sammeln und dann mit einem Funktionsaufruf schreiben!#" & @CRLF
    $sToWrite &= "# Created with Excel to EEP programme" & @CRLF
    $sToWrite &= "# User: " & 'XXXXX' & " Date: " & @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF
    $sToWrite &= "# Project File: " & 'YYYYYY' & @CRLF
    $sToWrite &= "# Remarks: " & 'ZZZZZZ' & @CRLF
    $sToWrite &= "#################################################################################" & @CRLF
    $sToWrite &= @CRLF
    Local $file = FileOpen("test.txt", 1 + 8)
    If $file = -1 Then Exit MsgBox(0, "Fehler", "Die Datei konnte nicht geöffnet werden.")
    FileWrite($file, $sToWrite)
    FileClose($file)

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

    #cs
    ; aus der Hilfe!
    Local $file = FileOpen("test.txt", 1)

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

    ; Prüfen, ob Datei im Schreibmodus geöffnet ist
    If $file = -1 Then
    MsgBox(0, "Fehler", "Die Datei konnte nicht geöffnet werden.")
    Exit
    EndIf

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

    FileWrite($file, "Zeile 1")
    FileWrite($file, "Immer noch Zeile 1" & @CRLF)
    FileWrite($file, "Zeile 2")

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

    FileClose($file)
    #ce

    [/autoit]