_Pack_String() & _DePackString()

  • Hallooooo Community :D

    Viele wissen vielleicht von meinem WinRar (oder so ähnlich^^) Projekt. Ich habs hinbekommen mehrere Dateien in 1 zu speichern, jedoch änderte sich nichts an der Größe.
    Das kann man aber mit diesen 2 Funktionen ändern :thumbup:
    Ich hab noch nicht viel Ahnung von Functionen schreiben, also gebt mir bitte noch ein paar Tipps, vor allem im Thema "SetError".
    Aber vielleicht kann ja jemand was mit anfangen ^^

    Spoiler anzeigen
    [autoit]

    Func _Pack_String($sString)
    Local $aOneWord[1], $zaehler = 0, $aSame[1], $sEndString = "", $All = ""
    If $sString = "" Then
    SetError(1)
    Return "2| | |"
    EndIf
    If $sString <> "" Then
    $words = StringSplit($sString, " ", 1)
    If IsArray($words) Then
    Local $aSame[$words[0] + 5][2]
    For $i = 1 To $words[0]
    If _ArraySearch($aOneWord, $words[$i] ) = -1 Then
    _ArrayAdd($aOneWord, $words[$i] )
    If $aSame[$i - 1][1] = "" Then
    $aSame[$i - 1][1] = $zaehler + 1
    $aSame[$i - 1][0] = $words[$i]
    EndIf
    If $aSame[$i - 1][1] <> "" Then
    $aSame[$i][1] = $zaehler + 1
    $aSame[$i][0] = $words[$i]
    EndIf
    $zaehler = $zaehler + 1
    EndIf
    If _ArraySearch($aOneWord, $words[$i] ) <> -1 Then
    $sEndString = $sEndString & $aSame[_ArraySearch($aSame, $words[$i] )][1] & "|"
    EndIf
    Next
    EndIf
    EndIf
    For $i = 1 To UBound($aOneWord) - 1
    If $aOneWord[$i] <> "" Then $All = $All & $aOneWord[$i] & "|"
    Next
    $All = $All & $sEndString
    $end = UBound($aOneWord) & "|" & $All
    Return $end
    EndFunc ;==>_Pack_String

    [/autoit]
    Spoiler anzeigen
    [autoit]

    Func _DePack_String($sPackedString)
    Local $alle = "", $dick = 0
    If $sPackedString = "" Then
    SetError(1)
    Return -1
    EndIf
    $data = StringSplit($sPackedString, "|")
    If IsArray($data) Then
    Local $aTable[$data[0]]
    Local $aTables[$data[0] + 5]
    For $i = 2 To $data[1]
    $aTables[$i] = $data[$i]
    $aTable[$i] = $i - 1
    Next
    For $i = $data[1] To $data[0]
    $dick = _ArraySearch($aTable, $data[$i])
    If $dick <> -1 Then $alle = $alle & $aTables[$dick] & " "
    Next
    EndIf
    Return $alle
    EndFunc ;==>_DePack_String

    [/autoit]

    Wichtig: _PackString gibt einen String zurück der am Anfang immer alle Vorkommenden Wörter 1mal beinhaltet. Diese werden danach immer als Zahl geschrieben.
    Beispiel:

    Spoiler anzeigen
    [autoit][/autoit] [autoit][/autoit] [autoit]

    $s = InputBox("Angabe", "Gib einen String an (Mehrere Wörter, die doppelt vorkommen")
    $test = _Pack_String($s)
    MsgBox(0, "", $test) ; hier sieht man wie der gepackte String aussieht
    $test2 = _DePack_String($test)
    MsgBox(0, "", $test2) ; hier ist der String wieder normal

    [/autoit]


    Mein fertiges Projekt erscheint innerhalb der nächsten Woche

    PS: weis jemand wie ich eine ausgelesene Binary bei _PackString splitten soll??? ich hab keine brauchbare Idee ?(

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • ich weiß ;( aber ich weiß nicht wie ich ne Binärdatei Splitten soll -.- geht das iwie nach allen 10 Zeichen oder so?

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • Zitat

    Für Textdateien, ok, aber bei Binärdaten wird das nicht funktionieren.
    Dort gibt es keine "Leerzeichen" und "Wörter".

    naja, 2x8Bit sind ja auch ein "word"^^
    Das Prinzip ist jedenfalls universell anwendbar, bei einer 2-Farben Bitmap (Monochrom) die nicht gerade extrem gedithered ist, sollte man auch zu schönen Ergebnissen kommen. Bei einem gescannten Text zum Beispiel.
    Hast mich auf ne Idee gebracht....

  • dann hab ich mit meiner Funk ja vielleicht doch was intelligentes geschaffen :D
    Edit: 110 Post :rock: :D

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]

    Einmal editiert, zuletzt von GE IXI TIM (2. Oktober 2009 um 17:26)

  • Hallo GE IXI TIM,

    hab deine Routinen gerade mit diesem Skript getestet:

    Spoiler anzeigen
    [autoit]

    #include <INet.au3>
    #include <array.au3>

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

    $sText = _INetGetSource("http://www.autoit.de/index.php?page=Thread&threadID=14844")
    MsgBox(0,"Start","Jetzt geht's los!")
    $tDiff = TimerInit()
    $sGepackt = _Pack_String($sText)
    $sEnpackt = _DePack_String($sGepackt)
    $tDiff = TimerDiff($tDiff)
    if $sText = $sEnpackt then
    MsgBox(0,"Gratuliere","Hat geklappt!" & @crlf & "Dauer: " & $tDiff)
    Else
    MsgBox(0,"Satz mit X","War wohl nix!" & @crlf & "Dauer: " & $tDiff)
    EndIf

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

    Func _Pack_String($sString)
    Local $aOneWord[1], $zaehler = 0, $aSame[1], $sEndString = "", $All = ""
    If $sString = "" Then
    SetError(1)
    Return "2| | |"
    EndIf
    If $sString <> "" Then
    $words = StringSplit($sString, " ", 1)
    If IsArray($words) Then
    Local $aSame[$words[0] + 5][2]
    For $i = 1 To $words[0]
    If _ArraySearch($aOneWord, $words[$i] ) = -1 Then
    _ArrayAdd($aOneWord, $words[$i] )
    If $aSame[$i - 1][1] = "" Then
    $aSame[$i - 1][1] = $zaehler + 1
    $aSame[$i - 1][0] = $words[$i]
    EndIf
    If $aSame[$i - 1][1] <> "" Then
    $aSame[$i][1] = $zaehler + 1
    $aSame[$i][0] = $words[$i]
    EndIf
    $zaehler = $zaehler + 1
    EndIf
    If _ArraySearch($aOneWord, $words[$i] ) <> -1 Then
    $sEndString = $sEndString & $aSame[_ArraySearch($aSame, $words[$i] )][1] & "|"
    EndIf
    Next
    EndIf
    EndIf
    For $i = 1 To UBound($aOneWord) - 1
    If $aOneWord[$i] <> "" Then $All = $All & $aOneWord[$i] & "|"
    Next
    $All = $All & $sEndString
    $end = UBound($aOneWord) & "|" & $All
    Return $end
    EndFunc ;==>_Pack_String

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

    Func _DePack_String($sPackedString)
    Local $alle = "", $dick = 0
    If $sPackedString = "" Then
    SetError(1)
    Return -1
    EndIf
    $data = StringSplit($sPackedString, "|")
    If IsArray($data) Then
    Local $aTable[$data[0]]
    Local $aTables[$data[0] + 5]
    For $i = 2 To $data[1]
    $aTables[$i] = $data[$i]
    $aTable[$i] = $i - 1
    Next
    For $i = $data[1] To $data[0]
    $dick = _ArraySearch($aTable, $data[$i])
    If $dick <> -1 Then $alle = $alle & $aTables[$dick] & " "
    Next
    EndIf
    Return $alle
    EndFunc ;==>_DePack_String

    [/autoit]

    hatte leider keinen Erfolg,

    mfg (Auto)Bert

    • Offizieller Beitrag

    Für das erstellen eines Wörterbuchs mit Häufigkeit der Wörter ist das Scripting.Dictionary-Objekt ideal:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <Inet.au3>

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

    $sText = _INetGetSource("http://www.autoit.de/index.php?page=Thread&threadID=14844")
    MsgBox(0,"Start","Jetzt geht's los!")
    $tDiff = TimerInit()
    $aText = _CreateWordDictionary($sText)
    ConsoleWrite("Dauer: " & TimerDiff($tDiff) & @CR)
    _ArraySort($aText, 1, 0, 0, 1)
    _ArrayDisplay($aText)

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

    Func _CreateWordDictionary($sText)
    Local $oDictionary, $aWords, $iCount
    If $sText = '' Then Return SetError(1, 0, 0)
    $sText = StringRegExpReplace($sText, '[\v\t]', '') ; alle vertikalen Whitespaces sowie alle TABs entfernen
    $oDictionary = ObjCreate('Scripting.Dictionary') ; Scripting.Dictionary-Objekt erstellen
    If Not IsObj($oDictionary) Then Return SetError(2, 0, 0)
    $aWords = StringSplit($sText, ' ', 2) ; Text an Leerzeichen splitten
    For $i = 0 To UBound($aWords) - 1 ; alle Wörter durchgehen
    If $aWords[$i] <> '' Then
    If Not $oDictionary.Exists($aWords[$i]) Then ; wenn das Wort noch nicht im Dictionary vorhanden, dann...
    $oDictionary.Add($aWords[$i], 1) ; das Wort hinzufügen und den Wert der Häufigkeit auf 1 setzen
    Else
    $oDictionary.Item($aWords[$i]) = $oDictionary.Item($aWords[$i]) + 1 ; das Wort war vorhanden, also den Zähler erhöhen
    EndIf
    EndIf
    Next
    $iCount = $oDictionary.Count ; Anzahl der Wörter im Wörterbuch holen
    Local $aOut[$iCount][2] ; 2D Array erstellen
    $x = 0
    For $strKey in $oDictionary.Keys ; Schleife für die Wörter (Key)
    $aOut[$x][0] = $strKey ; die Wörter dem Array zuweisen
    $x += 1
    Next
    $x = 0
    For $strItem in $oDictionary.Items ; Schleife für die Häufigkeit (Item)
    $aOut[$x][1] = $strItem ; die Häufigkeit dem Array zuweisen
    $x += 1
    Next
    Return $aOut ; das Array zurückgeben
    EndFunc

    [/autoit]
  • autoBert, was genau hat nicht geklappt? Das der Ausgangstext der selbe ist? oder das es solange dauert? ich glaube letzteres weil bei großen texten packt/entpackt er ziemlich lange :D ich teste dein beispiel gerade (schon seit 3-4 min -.-) Ich weiß aber nicht wie ich es schneller machen soll ;(
    Probiers mal mit kleinen Strings :) Dann gehts :) Bringt einem zwar nicht viel ne Textdatei mit 100 Wörtern zu packen, aber... :D:D:D

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • Setz die $sText und $sEntPackt mal genau untereinander in eine Msgbox...DER TEXT IST GENAU DER SELBE! auch keine Leerzeichen mehr oder ähnliches... Aber warum erkennt er nicht dass es der selbe Text ist?

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • Hallo GE IXI TIM,

    nein die beiden Strings sind unterschiedlich, auch wenn man es nicht sieht. Beweis: lass mal dieses Skript laufen

    Spoiler anzeigen
    [autoit]

    #include <INet.au3>
    #include <array.au3>

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

    $sText = "Dies ist ein Test! Ich bin auch ein Test. Auch das ist ein Test. Ist das Test Programm auch ein Test? Manche Programme sind Test Programme"
    ;$sText = _INetGetSource("http://natune.net/zitate/autor/Heinz+Erhardt")
    MsgBox(0,"Start","Jetzt geht's los!")
    $tDiff = TimerInit()
    $sGepackt = _Pack_String($sText)
    $sEnpackt = _DePack_String($sGepackt)
    $tDiff = TimerDiff($tDiff)

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

    $iLenG = StringLen($sGepackt)
    $iLenO = StringLen($sText)
    $iLenE = StringLen($sEnpackt)
    if $sText = $sEnpackt then
    MsgBox(0,"Gratuliere","Hat geklappt!" & @crlf & @crlf & "Dauer: " & $tDiff & @CRLF & "Länge org:" & $iLenO & @CRLF & "Länge gepackt:" & $iLenG & @CRLF & "Länge entpackt:" & $iLenE)
    Else
    MsgBox(0,"Satz mit X","War wohl nix!" & @crlf & @crlf & "Dauer: " & $tDiff& @CRLF & "Länge org:" & $iLenO & @CRLF & "Länge gepackt:" & $iLenG & @CRLF & "Länge entpackt:" & $iLenE)
    EndIf

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

    ConsoleWrite($sText & @CRLF)
    ConsoleWrite($sEnpackt & @CRLF)

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

    Func _Pack_String($sString)
    Local $aOneWord[1], $zaehler = 0, $aSame[1], $sEndString = "", $All = ""
    If $sString = "" Then
    SetError(1)
    Return "2| | |"
    EndIf
    If $sString <> "" Then
    $words = StringSplit($sString, " ", 1)
    If IsArray($words) Then
    Local $aSame[$words[0] + 5][2]
    For $i = 1 To $words[0]
    If _ArraySearch($aOneWord, $words[$i] ) = -1 Then
    _ArrayAdd($aOneWord, $words[$i] )
    If $aSame[$i - 1][1] = "" Then
    $aSame[$i - 1][1] = $zaehler + 1
    $aSame[$i - 1][0] = $words[$i]
    EndIf
    If $aSame[$i - 1][1] <> "" Then
    $aSame[$i][1] = $zaehler + 1
    $aSame[$i][0] = $words[$i]
    EndIf
    $zaehler = $zaehler + 1
    EndIf
    If _ArraySearch($aOneWord, $words[$i] ) <> -1 Then
    $sEndString = $sEndString & $aSame[_ArraySearch($aSame, $words[$i] )][1] & "|"
    EndIf
    Next
    EndIf
    EndIf
    For $i = 1 To UBound($aOneWord) - 1
    If $aOneWord[$i] <> "" Then $All = $All & $aOneWord[$i] & "|"
    Next
    $All = $All & $sEndString
    $end = UBound($aOneWord) & "|" & $All
    Return $end
    EndFunc ;==>_Pack_String

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

    Func _DePack_String($sPackedString)
    Local $alle = "", $dick = 0
    If $sPackedString = "" Then
    SetError(1)
    Return -1
    EndIf
    $data = StringSplit($sPackedString, "|")
    If IsArray($data) Then
    Local $aTable[$data[0]]
    Local $aTables[$data[0] + 5]
    For $i = 2 To $data[1]
    $aTables[$i] = $data[$i]
    $aTable[$i] = $i - 1
    Next
    For $i = $data[1] To $data[0]
    $dick = _ArraySearch($aTable, $data[$i])
    If $dick <> -1 Then $alle = $alle & $aTables[$dick] & " "
    Next
    EndIf
    Return $alle
    EndFunc ;==>_DePack_String

    [/autoit]


    Das ist die Ausgabe nach dem Test von deinem Thread:

    Zitat

    ---------------------------
    Satz mit X
    ---------------------------
    War wohl nix!
    Dauer: 872551.775155781

    Länge org:610352

    Länge gepackt:130761

    Länge entpackt:619964

    Bei einfacheren Test kam ich immer auf den Unterschied von 2 Bytes


    mfg (Auto)Bert

    3 Mal editiert, zuletzt von AutoBert (3. Oktober 2009 um 13:36)

  • Hallo,
    du kannst ja den Binärcode des Objektes, was du splitten willst angucken.
    Dann ungefähr alle 100 Zeichen speicherst du diese in eine neue Datei.
    (Ich habe keine Ahnung von Binärcode, ich weiß nicht ob 100 Zeichen viel oder wenig sind)
    Dann hast du ein paar Parts.
    Diese kannst du dann auch nach der Reihe wieder einlesen (WinRar, löst das ja nur Nummern in der Endung)
    Dann alles in eine Datei schreiben und Zack, hast du es wieder zusammengefügt.

  • danke für eure hilfe, aber ich glaub ich lass (vorerst) mal die Finger davon :D Da ich Binärcode nicht splitten kann, bringt mir das auch nichts :D

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]