String endet nach 1022 Zeichen

  • Sonstiges

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • String endet nach 1022 Zeichen

    Hallo zusammen,

    ich bin nun seit kurzer Zeit dabei an einem bestehendem Projekt weiter zu schreiben. Allerdings bin ich nun auf ein Problem gestoßen, dass ich zwar mit etlichen Testausgaben (so glaube ich) gefunden habe. Mit fällt nur nach langem überlegen keine Lösung ein. Vielleicht hat von euch ja jemand eine Idee die mich zur Lösung bringt.

    In dem Abschnitt werden die SQL-Abfragen zusammen gebaut. Allerdings ist eine Abfrage immer zu kurz und ist daher natürlich nicht SQL-Konform.
    Die 1. Abfrage wird immer nach 1022 Zeichen abgeschnitten.
    Die 2. Abfrage wird vollständig zusammen gebaut und funktioniert auch.
    Ich habe auch schon mehrere Versuche unternommen die Abfrage zubauen. Das Ergebnis ist bisher immer das selbe gewesen.
    Die Werte die genutzt werden, habe ich einzelnd auf richtigkeit geprüft. Dabei sind mir keine Fehler aufgefallen.

    C-Quellcode

    1. // 1. Versuch - Einfach mit der "format" Funktion.
    2. _sqlAnfrage = format["REPLACE INTO %1 (%2) VALUES(%3);", _datenbankTabelle, _listeSpaltenNamen, _listeSpaltenWerte];
    3. // 2. Versuch - Die Strings hintereinander zuhängen.
    4. _sqlAnfrage = "REPLACE INTO "
    5. + _datenbankTabelle
    6. + " ("
    7. + _listeSpaltenNamen
    8. + ") VALUES ("
    9. + _listeSpaltenWerte +
    10. ");";
    11. // 3. Versuch - Das ganze nochmal, allerdings immer nur einen weiteren String.
    12. _sqlAnfrage = "REPLACE INTO ";
    13. _sqlAnfrage = _sqlAnfrage + _datenbankTabelle;
    14. _sqlAnfrage = _sqlAnfrage + " (";
    15. _sqlAnfrage = _sqlAnfrage + _listeSpaltenNamen;
    16. _sqlAnfrage = _sqlAnfrage + ") VALUES (";
    17. _sqlAnfrage = _sqlAnfrage + _listeSpaltenWerte;
    18. _sqlAnfrage = _sqlAnfrage + ");";
    19. _sqlAnfrage = format["%1", _sqlAnfrage];
    20. // 4. Versuch - Und noch einmal, diesmal rückwärts, damit die Testausgaben lesbar sind.
    21. _sqlAnfrage = ");";
    22. _sqlAnfrage = _listeSpaltenWerte + _sqlAnfrage;
    23. _sqlAnfrage = ") VALUES (" + _sqlAnfrage;
    24. _sqlAnfrage = _listeSpaltenNamen + _sqlAnfrage;
    25. _sqlAnfrage = " (" + _sqlAnfrage;
    26. _sqlAnfrage = _datenbankTabelle + _sqlAnfrage;
    27. _sqlAnfrage = "REPLACE INTO " + _sqlAnfrage;
    28. _sqlAnfrage = format["%1", _sqlAnfrage];
    Alles anzeigen



    Ich habe bei Versuch 3 und 4 zwischen jeder Zeile eine Testausgabe eingefügt. Diese habe ich zur übersicht hier entfernt.
    Da vorallem die Ausgabe des 4. Versuches etwas zeigt, hänge ich nur diese an.
    Mir ist klar, dass die Ausgabe im ersten Moment sehr chaotisch aussieht. Ich habe überlegt wie ich sie für euch besser darstellen kann, allerdings ist mir keine einfache Variante eingefallen.

    Die Ausgabe ist in mehrere Blöcke unterteilt. Jeder Block stellt eine Ausgabe zwischen den Zeilen dar, in denen der String gebaut wird.
    Es ist zu erkennen, dass bei der 1. Abfrage der String nur 1022 Zeichen lang ist. Immer wenn vorne neue Werte angefügt werden, verschiebt sich zwar der ganze Test, allerdings bleibt der String eben nur 1022 Zeichen lang.
    Bei der 2. Abfrage ist dies nicht so.
    Nach ca. 1000 Zeichen macht meine Ausgabe immer einen Umbruch. Diesen habe ich nun bewusst gelassen, denn bei der 1. Abfrage ist zu erkennen, dass bei der letzten Ausgabe die letzten 2 Zeichen ");" wieder auftauchen, die bei den Ausgaben zuvor verschwunden sind.

    Da ich mit den Ausgaben die 10.000 Zeichen Grenze dezent überschreite, hänge ich die Ausgaben als Anhänge an.


    Ich weiß, dass dies sehr viel Text ist. Ich danke schonmal vorab jedem, der sich die Zeit und vorallem Nerven nimmt, sich dieses Problem anzusehen.
    Ich hoffe darauf, dass jemand eine Idee hat woran es liegen könnte.

    Wenn etwas undeutlich ist, versuche ich es besser/anders zu beschreiben.


    Mit Hoffnung auf eine Lösung.
    Grüße
    Henne
    Dateien
  • Dein problem hierbei ist das format. format erlaubt nur bestimmte größe and bytes. und diese endet glaube ich bei 2048 bytes.
    dazu denke ich sendest du den ganzen output an eine DLL wo du auch wieder eine maximale ausgabe hast von 10240 bytes.
    hier bei ist zu beachten das 1 byte != 1 Char. denn sobald du aus der ACSII range raus gehst werden Chars mit mehr als 1 byte dagestellt, ich glaube bis zu 4 bytes in dem arma genutzen system.

    die Lösung for format is dsa nutzen von formatText und ein str. jedoch die lösung für die extension output is etwas harter weil du musst dort ein eigenes system bauen das die daten in chunks exportiert und dann zusammen zu fügen und dann auszuführen
    Wer Rechtschreibfehler findet darf sie behalten
    ACE3 Core Developer
    CBA A3 Developer
    Developer of Lambs Danger, Dynasound, Enhance SoundScape, Immerse, Suppress and Align
  • Also in V3 und V4 im Opening Post könnten Strings mit bis zu 10 Millionen Zeichen verwendet werden, wenn man das absolut sinnlose format["%1", ...] weglässt. Mit format sind es dann 8192. diag_log selbst ist begrenzt auf 1044 Zeichen, also wahrscheinlich machst du einen Fehler im Debugging, der schwer nachvollziehbar ist, weil du das falsche / unvollständige Skript gepostet hast.
    Auch nicht gezeigt wird ob und wie callExtension verwendet wird. Das selbst ist begrenzt auf 10240 Bytes lt. Wiki.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von commy2 ()

  • Ein Lösungsansatz wäre, die Item Classnames per Server am Missionsstart in Zahlen umzuwandeln.

    C-Quellcode

    1. // preInit
    2. if (isServer) then {
    3. commy_itemClassnameToId = "Building" createVehicle [0,0,0];
    4. publicVariable "commy_itemClassnameToId";
    5. commy_itemIdToClassname = "Building" createVehicle [0,0,0];
    6. publicVariable "commy_itemIdToClassname";
    7. private _classnames = "getNumber (_x >> 'scope') >= 1" configClasses (configFile >> "CfgWeapons") apply {configName _x};
    8. {
    9. commy_itemClassnameToId setVariable [_x, str _forEachIndex, true];
    10. commy_itemIdToClassname setVariable [str _forEachIndex, _x, true];
    11. } forEach _classnames;
    12. commy_itemClassnameToId setVariable ["", "-1", true];
    13. commy_itemIdToClassname setVariable ["-1", "", true];
    14. };
    15. // mid mission script
    16. private _itemId = commy_itemClassnameToId getVariable [_item, _item];
    17. private _item = commy_itemClassnameToId getVariable [_itemId, _itemId];
    Alles anzeigen
    Das kann man natürlich auch noch weiter treiben, indem man Hexadezimalzahlen verwendet, oder auch einfach das ganze Alphabet ausreizt. Man muss dann nur alles vor und zurückkonvertieren.
  • jokoho482 schrieb:

    dazu denke ich sendest du den ganzen output an eine DLL wo du auch wieder eine maximale ausgabe hast von 10240 bytes.
    ausgabe != eingabe.
    Und das könnte man umgehen indem man in den Input schreibt.

    Ich persönlich nutze lieber joinString und + um solche großen Abfragen zu bauen. Anstatt format.

    commy2 schrieb:

    Auch nicht gezeigt wird ob und wie callExtension verwendet wird.
    Ich würde auch gerne das komplette script inklusive callExtension sehen.

    Henne schrieb:

    _sqlAnfrage = format["%1", _sqlAnfrage];
    Das einzige was das tut ist nochmal Anführungszeichen um die Anfrage zu packen oder? Wieso packst du die nicht von Anfang an direkt mit rein?
  • Ich danke allen für die zahlreichen Antworten.
    Ich habe nun mehrere Test durchgeführt. Dies sind die Ergebnise:



    Das nutzen von "formatText": Selbes Ergebnis wie bei "format".
    Entfernen von "format": Selbes Ergebnis wie mit "format".



    Zum Thema Debuging:
    Ich habe mir eine kleine Datei geschrieben, die die String in 1000 Blöcke unterteilen soll und diese dann mit diag_log ausgibt.
    Mit Sicherheit lässt sich das noch verbessern. Meinen bisherigen Anforderungen hat dies gereicht.

    C-Quellcode: functions/030_allgemeines/fn_debuglog.sqf

    1. _text = [_this,0,""] call BIS_fnc_param;
    2. _thema = [_this,1,""] call BIS_fnc_param;
    3. diag_log format["<-- DEBUGLOG: %1 START -->", _thema];
    4. while {true} do {
    5. if (count _text > 1000) then {
    6. diag_log (_text select [0, 1000]);
    7. _text = (_text select [1000, (count _text - 1000)]);
    8. } else {
    9. diag_log (_text select [0,count _text]);
    10. _text = (_text select [count _text, 0]);
    11. };
    12. if (count _text == 0) exitWith{};
    13. };
    14. diag_log format["<-- DEBUGLOG: %1 ENDE -->", _thema];
    Alles anzeigen
    Die Datei ist in der cfgFunctions.h eingetragen und der "tag" ist auf "schmitt" gesetzt.
    Ich rufe die Funktion so auf:
    [_sqlAnfrage] spawn schmitt_fnc_debuglog;

    Bei der 2. Abfrage funktioniert dieses auch sehr gut, die vollständige Abfrage wird ausgegeben (auf mehrere diag_log´s aufgeteilt).

    Da die 1. Ausgabe nur zur "hälfte" ausgegeben wird und es bei der 2. Abfrage tadellos funktioniert. Bin ich bisher davon ausgegangen, dass der String wirklich nicht mehr enthält, als ich ausgegeben bekomme.




    Es wird "callExtension aufgerufen, allerdings zeigen die Ausgaben, dass die Abfrage zuvor schon unvollständig ist.
    _sqlErgebnis = call compile ("extDB3" callExtension "2:"+_sqlAbfrage);




    commy2 schrieb:

    Ein Lösungsansatz wäre, die Item Classnames per Server am Missionsstart in Zahlen umzuwandeln.
    Da muss ich jetzt leider sagen, dass ich mit dem Code-Abschnitt nicht so viel anfangen kann, bzw. nicht weiß wie mir das weiter helfen soll.




    Da der Wunsch geäußert wurde, dass ich den kompletten Script zeige habe ich nun das Repository in dem ich arbeite auf Öffentlich gestellt.
    europsuchtis.eu:8081/ESARMA/Sc…sting/SchmittysLife.Altis

    Es handelt sich vorallem um folgende Dateien:

    Hier wird die Abfrage zusammen gebaut und hier werden auch die Testausgaben ausgeführt.
    europsuchtis.eu:8081/ESARMA/Sc…AnfrageEinreihen.sqf#L216

    Hier wird die SQL-Abfrage durchgeführt. Es ist durch den ursprünglichen Author vorgesehen, dass alle Anfragen zusammen geführt werden, um nur eine Abfrage durchzuführen.
    Mit meiner Debug-Funktion ist zu erkennen, dass die 1. Abfrage nur zur "häfte", die 2. Abfrage aber vollständig vorhanden ist. Dadurch ist die SQL-Abfrage natürlich nicht SQL Konform und die Abfrage wird nicht ausgeführt.
    europsuchtis.eu:8081/ESARMA/Sc…fragenAusfuehren.sqf#L117




    Ich hoffe das ganze wird ein wenig durchsichtiger.

    Gruß Henne

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Henne () aus folgendem Grund: Habe die fn_debuglog.sqf überarbeitet. Die Ergebnise sind identisch.

  • Henne schrieb:

    Da muss ich jetzt leider sagen, dass ich mit dem Code-Abschnitt nicht so viel anfangen kann, bzw. nicht weiß wie mir das weiter helfen soll.
    Mein Skriptfragment würde die langen Classnames in kurze Zahlen umwandeln und damit die Länge des übergeben String reduzieren.

    Warum muss denn überhaupt ein so großer String übergeben werden? Es erscheint mir erheblich sinnvoller, einfach callExtension mehrmals und mit kleineren Strings auszuführen.
  • Jetzt verstehe ich was du meinst.


    Ich habe gerade nachgelesen, da der "REPLACE INTO"-Befehl genutzt wird, ist es erforderlich, dass alle Werte die gespeichert werden sollen übergeben werden.
    Die Funktion auf "INSERT INTO" und "UPDATE" umzuschreiben wäre umständlich.

    Die einfache Variante ist wie es aktuell ist.
    Es muss doch aber einen Grund geben, warum nur der eine String an einer Stelle abgeschnitten wird.

    Ich habe eben gesehen, dass aus den beiden Strings später ein gemeinsamer großer String erstellt wird. In diesem String wird nichts gekürzt. Der String wird sogar durch ein format geschleust und trotzdem geht nichts verloren. Es muss also an dem 1. String liegen. Ich werde mir eine Möglichkeit überlegen, wie ich den String in noch kleinere Teilchen erstellen lassen kann.

    Vielleicht ist einer der Werte der auslöser. Ein "verborgenes" Zeichen? Das im diag_log nicht dargestellt wird, aber trotzdem vorhanden ist und zu diesem Fehler führt.

    Ich werde auf jeden fall noch weiter experimentieren.
    Vielleicht hat ja trotzdem noch jemand eine Idee woran es liegen könnte.
  • Henne schrieb:

    _text = (_text select [1000, (count _text - 1000)]);
    community.bistudio.com/wiki/select


    If "length" is omitted, selection will be made from "start" to the end of the string.

    Quellcode

    1. _text = _text select [1000];

    Ich habe jetzt endlich auch mal verstanden was das problem ist. Deine Ausgabe1 die du hochgeladen hast bricht immer nach exakt 1024 ab.
    Hast du denn schon mal versucht nur deine Eingabe Daten per diag_log auszugeben und zu schauen ob die in Ordnung sind?

    Wenn du immer noch das Konstrukt aus "_sqlAbfrage = _sqlAbfrage + ..." benutzt dann schau dir mal folgendes an:
    community.bistudio.com/wiki/joinString
    Das ist schneller und hat keine Längenlimitierung wie Format.



    europsuchtis.eu:8081/ESARMA/Sc…ageEinreihen.sqf#L238-251

    Was ist das denn? Du baust die Abfrage rückwärts auf? Warum so kompliziert?


    Übrigens hast du da bei spielerName eine mögliche SQL Injection drin.
  • Danke für den Tipp, dass wusste ich noch garnicht. Da werde ich das gleichmal umschreiben.



    Wie ich im Eingangspost erwähnt habe, habe ich die Variablen, die für den String genutzt werden geprüft und diese sind vollständig.
    Dabei habe ich zum prüfen der einzelnen Variablen diag_log, aber auch meine debuglog-Funktion genutzt. Das Ergebnis ist das selbe.
    Da jede Variable kürzer als 1000 Zeichen ist, war es auch kein Problem diese mit diag_log auszugeben.



    Das ist super zuwissen, dass es noch andere Möglichkeiten gibt den String "zubauen". Das werde ich auch gleichmal testen.
    Allerdings bezweifle ich das es einen Unterschied macht, da zwischen +, format und formatText auch kein Unterschied vorhanden ist.
    EDIT: Ich habe den Test nun durchgeführt, allerdings ist es die selbe Ausgabe wie bei den anderen Versuchen.



    Ich habe es rückwärts aufgebaut, damit ich die Ausgaben besser nachvollziehen kann, hier ein Beispiel:

    Quellcode

    1. Nehmen wir für dieses Beispiel an, dass der String bei 10 Zeichen endet.
    2. Grundwerte:
    3. 1. Dies
    4. 2. ist
    5. 3. ein
    6. 4. test
    7. Wenn der String von vorne aufgebaut wird, sieht die Ausgabe so aus:
    8. Dies
    9. Dies ist
    10. Dies ist e
    11. Dies ist e
    12. Wenn der String von hinten aufgebaut wird, sieht die Ausgabe so aus:
    13. test
    14. ein test
    15. ist ein te
    16. Dies ist e
    17. Es ist dadurch zu erkennen, dass alle Werte zwar angefügt werden, allerdings immer nur die ersten 10 Zeichen gespeichert/ausgegeben werden.
    Alles anzeigen

    Ich hoffe ich konnte meinen Gedanken damit nachvollziehbar erklären. Richtig, an sich ist es Schwachsinn und sobald das Problem gelöst ist, werde ich es auch rumdrehen, so wie man es normal auch macht. Wie im verlinkten Repository aber auch gut zu erkennen ist, sind dort meine Versuche alle vorhanden und auskommentiert. Nur mein aktueller Versuch wird immer ausgeführt.



    Ich habe die Abfrage ursprünglich nicht erstellt, allerdings wüsste ich nicht wo in der SQL-Abfrage ein Fehler sein sollte. Denn ich habe die Variablen ausgegeben, die Abfrage dann selber erstellt und diese dann in MySQL ausgeführt. Die Abfrage (wenn sie vollständig ist) funktioniert einwandfrei. Vielleicht kannst du deine Bedenken genauer beschreiben.



    EDIT:
    Habe jetzt nochmal einen Test durchgeführt. Ich habe meine Werte genommen und einfach hintereinander hängen lassen. Dabei gibt es normal keine Probleme.
    Nur bei folgendem String taucht dieser Fehler auf:

    Quellcode

    1. '76561198010416315', 'ziv', 'fra_ziv', 'Henne', 'U_C_Poloshirt_blue', '', 'B_OutdoorPack_blk', '', '', '["""","""","""",""""]', '["""","""","""",""""]', '["""","""","""",""""]', '[]', '[]', '[""ItemMap"",""ItemCompass"",""ItemWatch"",""ItemGPS""]', '', '', '[]', '[]', '[]', '[[""wasser"",[""KM"",""KM"",""KN"",""KN"",""XX""]],[""diamant"",[""KM"",""KM"",""KM"",""KN"",""KN"",""KN""]],[""bombe"",[""KM"",""KN""]],[""brandsatz"",[""KN"",""KN"",""KN"",""KN""]],[""apfel"",[""XX""]]]', '[[""ventil"",1000],[""steuereinheit"",1000],[""spitzhacke"",1000],[""schaufel"",1000],[""reagenz"",1000],[""axt"",1000],[""mixer"",1000],[""korb"",1000],[""messer"",1000],[""kanister"",1000],[""pinzette"",1000]]'
    Das sind alle Werte die in die Datenbank geschrieben werden sollen.

    Mit meiner Debug-Funktion wird der von mir erstellte lange String in mehrere Abschnitte geteilt. Jeder Abschnitt unterbricht dabei nach 1022 Zeichen (warum nicht nach 1000 wie er eigentlich soll, habe ich bisher nicht feststellen können). Die Ausgabe wird mit dem nächstem Abschnitt fortgesetzt. Allerdings fehlen zwischen den Abschnitten 130-150 Zeichen. Eine Regelmäßigkeit ist mir bisher nicht aufgefallen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Henne () aus folgendem Grund: Den Test durchgeführt, die Abfrage mithilfe von "joinString" zu erstellen. Die Ergebnisse des Test mit langen String angefügt.

  • Da ich die Abfrage nicht selber erstellt habe, sondern nur auf dieses Problem gestoßen bin, versuche ich nun dieses Problem zu beheben.
    Da ich jetzt ja zumindestens die Fehlerquelle auf den String mit den Werten eingrenzen konnte werde ich jetzt noch einige Versuche damit anstellen. So hoffe ich, stoße ich bald auf die Fehlerquelle.

    Nachdem ich meine Strings die ich zum testen genutzt habe genauer verglichen habe, bin ich aber zu einem ähnlichen Schluss gekommen. An so etwas, oder ähnlichen wird es vermutlich liegen.

    Sobald ich einige Test durchgeführt habe und so mehr Informationen habe, werde ich mich wieder melden.
  • Ich habe 2 lange (mehr als 1000 Zeichen) Strings (SQL-Abfragen/Anweisungen).

    Diese werden erstellt und ausgeführt, dabei ist mir aufgefallen, dass einer der beiden Strings nicht vollständig ist (nach 1022 Zeichen).

    Mir ist bewusst, das diag_log nicht mehr ausgeben kann, also habe ich einen Code geschrieben, der genau dieses Problem löst und den String in Abschnitten ausgibt.

    Dabei sahen meine Aussgaben wie folgt aus:

    Quellcode

    1. Annahme: Der Fehler taucht nicht nach 1022 Zeichen auf, sondern schon nach 10.
    2. String 1: Dies ist ein Test.
    3. String 2: Ein weiterer Text.
    4. Ausgabe mit meinem Code:
    5. String 1:
    6. Dies ist e
    7. String 2:
    8. Ein weiter
    9. er Text.
    10. Schlussvolgerung:
    11. String 1 wird nicht vollständig gespeichert/ist fehlerhaft.
    Alles anzeigen
    Inzwischen könnte in den Bereich des Fehlers weiter eingrenzen der Grund ist ein Teil von String 1.

    Die Vermutung von Raven und mir ist das es an den vielen "" liegen könnte. Dazu werde ich heute noch Tests durchführen und mich melden sobald ich Ergebnisse habe.

    Dazu möchte ich nochmal erwähnen, dass die ursprünglichen Strings nicht von mir sind. Allerdings wollte ich bisher das Projekt auch nicht neu schreiben.

    Mir ist auch nicht bekannt wieweit das entfernen der "" einen Einfluss auf andere Teile des Projekts hat. Wobei diese Probleme aktuell zweitrangig sind solange der String vollständig ist.
  • Wir reden von SQF, ja?

    >Diese werden erstellt und ausgeführt

    STRINGs kann man nicht ausführen. Man kann nur CODE ausführen.
    Wenn ich:

    Quellcode

    1. private _longString = "<hier sehr langen String einfügen>";
    2. _longString
    schreibe ("erstelle"), dann ist mein Ausgabewert exakt der gleiche wie der Eingabewert, solange wie der jeweilige String kürzer als 10.000.000* Zeichen ist.

    Ich kann also deinen Fehler nicht reproduzieren.