Beiträge von AspirinJunkie

    Ich wiederhole im Grunde nur was Musashi bereits schon gesagt hat.
    Der Knackpunkt hier ist, die einzelnen Werte vor dem Sortieren in numerische Datentypen umzuwandeln.

    Dann ist die Abfolge im Prinzip aber ziemlich klar:


    1. Datei zeilenweise in Array einlesen
    2. Die einzelnen Elemente des Arrays in Zahlentypen konvertieren
    3. _ArraySort()
    4. [optional]: Zahlen wieder formatiert (z.B. immer mit 2 Nachkommastellen) als String formatieren
    5. Array in Datei rausschreiben.

    Beispielcode:

    sobald die Werte geändert werden werden diese mit den "" versehen, auch wenn vorher keine "" vorhanden waren.

    Dann enthält deine Änderung eine (implizite) Konvertierung in einen String. Also irgendeine Operation die aus dem vorherigen Zahlentyp eine Zeichenkette macht.

    Wenn du uns ein Beispiel deiner Änderung zeigtst können wir mehr sagen.


    Kannst Du mir noch ein Beispiel geben wie ich jetzt werde in einem untergeordneten Array in einem Json anpassen. Z.b. unten nun zusätzlich Rcon - Port

    Im Beispiel fehlt noch ein Komma hinter "StandardPvE".

    Zum besseren Verständnis was genau gemacht wird:

    • Die JSON-Datei wird in AutoIt-Datenstrukturen geparsed. Im Beispielfall wird die Variable $oJSON ein Dictionary (oder Map - je nach Einstellung) werden. Dieses hat Key-Value-Elemente. Als Value für den Key "Port" wird also ein Integer mit dem Wert 27015 eingetragen. Beim Key "RCON" wiederrum wird der Wert selbst wieder ein eigenes Dictionary/Map. Unter anderem mit dem Key "Password" mit dem dazugehörigen Wert "SecretPassword" als Stringtyp.
    • Dann passt man seine Werte innerhalb der AutoIt-Strukturen an. Man greift sich also erst das Dictionary, welches im Dictionary $oJSON unter dem Key "RCON" steht. In diesem Dictionary schnappt man sich den Wert der dort unter "Port" steht und ändert diesen.
    • Wir haben also Werte in der verschachtelten AutoIt-Datenstruktur verändert. Vom Grundaufbau ist dies immer noch genauso aufgebaut wie vorher - nur ein Wert wurde geändert. Diese AutoIt-Struktur können wir mit der Funktion _JSON_Generate dann in einen String konvertieren (man sagt "serialisieren" hierzu) welcher die Datenstruktur im Format JSON abbildet.

    Also was wichtig ist: JSON spielt nur eine Rolle beim Einlesen der Daten und am Ende beim wieder ausgeben. Alles was dazwischen passiert sind reine AutoIt-Typen und entsprechend müssen sie auch behandelt werden.
    Um nun also z.B. deinen Port im Subobjekt "RCON" zu ändern könnte man dies folgendermaßen durchführen:

    Es gibt verschiedene UDFs die einem die Arbeit mit JSON in AutoIt erleichtern.
    Eine davon ist meine: JSON-UDF


    Mit dieser würde das ganze exemplarisch so aussehen:


    Btw: momentan bastelt er standardmäßig JSON-Objekte in Scripting.Dictionary-Objekte um.
    Da Maps ja mittlerweile so gut wie stable sind, werde ich wohl die UDF nochmal so anpassen, dass standardmäßig AutoIt-Maps verwendet werden.

    Das sind zu wenig Infos und eine Frage, welche man beantworten könnte ist auch nicht vorhanden.


    Was genau verstehst du unter "prüfen"?
    Ob die Datei Syntaxkonform mit dem JSON-Standard ist oder ob bestimmte Attribute bestimmte Werte (welche genau?) aufweisen?

    Daher ergibt sich:



    Global $Return = String(_Crypt_EncryptData($sRead, $vCryptKey, $CALG_USERKEY))

    Das ist genau das was ich vorhin versucht habe zu erklären: Warum wollt ihr unbedingt das Ergebnis von _Crypt_EncryptData als Hex-String IN der Variable haben?

    Das braucht man doch nur für die Ausgabe oder eventuell den Export.

    Es ist daher sinnvoller $Return das direkte Binary aus dem Return von _Crypt_EncryptData zu belassen.

    Und erst sobald man die Daten sich in Hexdarstellung anschauen will, dann entsprechend erst dort die Konvertierung durchzuführen: ConsoleWrite(String($Return))


    Denn: Man schleppt nur sinnfrei Overhead mit sich rum.

    In dem Beispiel ist $Return ohne String() 4 Byte groß und wächst durch dieses dann vermeidbar auf 10 Byte an.

    Performanceoverhead gibt es durch die expliziten wie auch impliziten Konvertierungen ebenso - sind jedoch aber vernachlässigbar.

    Bei größeren zu verschlüsselnden Daten wird es entsprechend mehr ohne einen (für mich) erkennbaren Vorteil zu haben.


    Sprich: Die Daten selbst von deren Darstellung trennen.

    Hatte ich das oben nicht bereits bei #4 erwähnt bezüglich des Datentyps?^^

    Du hast vermutet, dass das Problem darin liegen könnte durch die implizite Konvertierung in einen String, in deinem Code dann aber sein Grundproblem nicht gelöst.


    Das BinaryToString ändert grundsätzlich nichts an den Daten sondern markiert diese lediglich als String.
    Für die Weiterverarbeitung erst einmal unschädlich, da damit auch das Decrypten auch funktioniert (Die Daten bleiben ja gleich) aber sein Ausgabeproblem mit ConsoleWrite bleibt bestehen.

    Daher ist das BinaryToString hier ziemlich sinnfrei.


    Vielleicht zum Verständnis nochmal zusammengefasst:

    Man hat eine Binärvariable $bEncrypted. Deren Inhalt ist die Bitfolge 10100011001110001101010111111001

    BinaryToString() interpretiert diese Bitfolge als ANSI-kodierten Text -> "£8Õù" (Die Bitfolge bleibt gleich)

    String() gibt die Hexadezimaldarstellung der Bitfolge als String zurück -> "0xA338D5F9" (als ANSI kodiert ist der Inhalt der Variable nun 0x307841333338443546390D0A)


    Sidewinder

    Nochmal zusammengefasst:
    Lass $bEncrypted so wie es ist - also $dEncrypted = _Crypt_EncryptData($sRead, $g_hKey, $CALG_USERKEY) (ohne BinaryToString drumherum)

    Willst du dir den Inhalt von $bEncrypted als Hex-Repräsentation in ConsoleWrite oder anderswoe ausgeben lassen dann so: ConsoleWrite(String($dEncrypted))

    Wichtig!: Nur für Ausgabezwecke zu einem String konvertieren. Willst du stattdessen dennoch mit der Hexrepräsentation weiterarbeiten musst du dann nämlich vor dem Decrypten sonst das ganze via Binary() zurück wandeln.

    Eigentlich müsste mein Script doch "0xA338D5F9" ausgeben. Es gibt aber "£8Õù" aus.

    Zitat aus der Hilfe zu ConsoleWrite:

    Binary data is written as-is. It will not be converted to a string. To print the hex representation of binary data, use the String() function to explicitly cast the data to a string.


    Heißt: $dEncrypted ist ordentlich vom Typ Binary und kann auch entsprechend weiterverwendet werden.
    Wenn du per Consolewrite die Hex-Repräsentation hiervon darstellen willst musst du noch ein String() drumrum machen.


    Mit "& @CRLF" wird der Wert dann korrekt ins Attribut geschrieben, aber im 2. Schritt dann nicht mehr korrekt entschlüsselt.

    Was auch logisch ist, da du die Daten ja komplett veränderst durch die implizite Konvertierung in einen String.

    Denn was passiert? Durch das & @CRLF wird $bEncrypted per String() in dessen Hexadezimaldarstellung gewandelt und als String ausgegeben. Sprich: $bEncrypted wird implizit zu "0xA338D5F9" & @CRLF. Wichtig - das ist jetzt ein String und keine Hex-Repräsentation der eigentlichen binären Daten. Stattdessen hat dadurch $bEncrypted nun den Wert 0x307841333338443546390D0A

    Daher kommt natürlich beim decrypten etwas völlig anderes raus.


    Lass also den Spaß mit dem & CRLF und verwende die $bEncrypted einfach unangetastet weiter.

    Für den Fall, dass man sowohl die Existenz als auch die Art abfragen möchte bietet sich dann aber eigentlich wieder eher FileGetAttrib an.

    Sprich:

    AutoIt
    If StringInStr(FileGetAttrib('E:\Test'), "D") Then ...


    Edit: Gerade gesehen, dass Musashi auch eine FileGetAttrib-Variante mit drin hat.
    Aber das extra FileExists braucht man eigentlich nicht mehr, da nur dann ein D im FileGetAttrib-Return drin ist, wenn der Pfad existiert UND ein Ordner ist.

    Na da lag ich mit meiner Schätzung, dass mein Skript etwa im Mittelfeld landet ja perfekt richtig :D


    Schade jedoch, dass es wirklich nur 3 Einsendungen gab.

    Das Interesse daran schien anfangs ja größer zu sein (Andy? :/ )

    Hätte gerne weitere Ansätze gesehen.

    Eventuell hatten einige Angst sich "zu blamieren", weil schon vorab Ergebnisse gepostet wurden?

    Das wäre wirklich schade, denn z.B. bei mir lag die Optimierung rein aus persönlichen Interesse auf der möglichst optimalen Huffman-Kodierung.
    Ich habe jedoch auch eine Vorkompilierung drin die wirklich simpel ist und in die ich nur wenig Zeit gesteckt habe.

    Hier hatte ich auf Ansätze von anderen gehofft, welche bisschen mehr rausholen - das Potential ist definitiv da.

    Am Ende hätte man ein kombiniertes Skript gehabt, welches noch höhere Kompressionsraten erreicht.


    Also wer ein Skript geschrieben hat, welches den String wieder selbst in einen String komprimiert, der mag ihn bitte bitte mit uns teilen - auch wenn er nicht an die anderen Ergebnisse ranreicht.

    Diese werden primär durch entsprechende Zeichenkodierung erreicht und eben nicht durch Veränderungen des Strings selbst - daher können uns solche Lösungen weiterhelfen.


    Zum Thema: "Performance-Krone": Ganz ganz ehrlich: ich hab nicht im Mindesten auf Performance hin optimiert. Mir fallen auf Anhieb 4 Stellen ein, die man durch umcoden noch beschleunigen könnte. Klar über die Zeit hat man gelernt, was Performance frisst und was nicht und hat sein normales coden daraufhin angepasst.

    Aber direkt auf Performance ist das Ding überhaupt nicht optimiert.

    Ebenso gibt es so gut wie kein Error-Handling, keine hinreichende Codedokumentation/kommentierung und getestet wurde ausschließlich mit diesem String.

    Bugs bei anderen Inputs halte ich für hinreichend wahrscheinlich.


    So - nun schaue ich mir aber mal genauer an was die anderen so fabriziert haben. :)


    Danke nochmal Oscar - hat wirklich Spaß gemacht! :rock:


    Edit: Oscar : Genau genommen ist die Kompressionsrate von Mars noch besser. Bei Ahnungslos und mir wird die Anzahl an Bytes des Eingangsstrings als Vergleichsgröße genommen (6105). Bei Mars hingegen ist es die Stringlänge (6033). Die Kompressionsrate bei ihm sollte also zum Vergleich eher 50,762 % betragen.

    Ne scheint schon so zu sein - hab es mal mit nem großen String probiert - kein relevanter Unterschied feststellbar:

    Ja klar - du könntest das auch ohne Const machen wenn du einfach in der Funktion von der Variable die Finger lässt.

    Das Const bringt hierzu lediglich zusätzlich:

    1. eine technische Schutzschicht vor Veränderungen und
    2. eine menschenlesbare Klarstellung darüber, dass nicht geplant ist diese Variable in der Funktion zu verändern. (wenn du später den Code anschaust weißt du sofort, dass das ByRef nur aus Performance-Gründen dort steht)

    Welchen Vorteil bringt das - wenn überhaupt?

    Beispiel: Du übergibst Strings mit mehreren Megabyte Größe an deine Funktion.
    In dieser willst du den String selbst nicht verändern - nur analysieren.

    Wie du selbst sagtest wäre eine Übergabe ohne ByRef unnötig lahm und frisst unnötig Speicher, da erst eine Kopie des Strings erstellt werden muss.

    Deswegen macht also schonmal ein ByRef Sinn.

    Um nun noch klar zu machen und ganz sicher zu gehen, dass du diesen String in der Funktion nicht veränderst, wird dann noch einfach das Const dazu geschrieben.


    Kurz: Sorgt dafür, dass sich außerhalb der Funktion die übergebene Variable nicht ändert und bleibt dennoch performant und Speicherfreundlich.

    was ist daran "extern"?

    Es ist Teil des VBA-Frameworks. Also kein Bestandteil des resultierenden AutoIt-Codes selbst.

    Was das heißt habe ich Live hier an dem Code erlebt: Denn auf einmal funktioniert die System.Collections.Hashtable aus dem .Net-Framework bei mir nicht mehr, auf welche ebenso wie das Dictionary zugegriffen wird.

    Es ist ein externes Objekt und wenn sich dort was ändert kann sich das Verhalten deines Programmes ändern ohne, dass das Programm selbst geändert wird.


    Bislang lief es wunderbar und daher nutze ich es auch gerne.
    Aber ein integriertes ist definitiv die schönere Option (Siehe HashTable).