Laden...

XmlDocument/LoadXml: String reißt einfach ab

Erstellt von diego2k vor 13 Jahren Letzter Beitrag vor 13 Jahren 8.722 Views
D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren
XmlDocument/LoadXml: String reißt einfach ab

Hallo,

ich weiß echt nicht mehr weiter, es sieht so aus als würd xmlDocument strings zerstören.
Ich erhalte über TCPIP eine XML dies muss ich dann später bearbeiten.
Allerdings wird so ca jeder 100erste String von .LoadXml zerstört.

Ausschnitt:


Console.WriteLine("X1: " + data.Length);
                string tempdata = String.Copy(data);
                Console.WriteLine("X1: " + data.Length);
                Console.WriteLine("Y1: " + tempdata.Length);
                XmlDocument _xmlAns = new XmlDocument();
                try
                {
                    _xmlAns.LoadXml(Convert.ToString(tempdata));
                }
                catch (Exception ex) 
                {
                    ///Console.WriteLine(ex.ToString());
                    Console.WriteLine("ERROR, LoadXML ...");
                }
                Console.WriteLine("Y2: " + tempdata.Length);
                Console.WriteLine("X2: " + data.Length);

Ausgabe:
X1:827
X1:827
Y1:827
ERROR, LoadXML ...
Y2:672
X2:672

Wie man sieht ist sogar die kopie davon betroffen...
Console.writeline zeigt vor LoadXML den ganzen string an, danach natürlich nur mehr das fragment.

Sonderzeichen und unreinheiten wurden vorher herausgefiltert mit:

      System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
                
                byte[] bytearry = enc.GetBytes(data);

                String tempstr = "";
                int momcahr = 0;
                for (int i = 0; i < data.Length; i++)
                {
                    momcahr = Convert.ToInt32(bytearry[i]);
                    if (momcahr >= 32 && momcahr <= 126)
                    {
                        tempstr += (char)momcahr;

                        strlen++;
                    }
                }
                data = Convert.ToString( tempstr);
                data = data.Remove(0, data.IndexOf("<?xml"));

Gelöschter Account
vor 13 Jahren

exceptiontext?

Gelöschter Account
vor 13 Jahren

speichere den tempstring bei einem fehler doch mal in sowas wie
errorfile.txt
irgendwas wird schon sein.
das da was zerstört wird kann ich mir nicht vorstellen.
(du vermutlich auch nicht wirklich)

Gelöschter Account
vor 13 Jahren

und nur so zur info, weil du das konsequent falsch machst:
[Artikel] Performant Strings verketten

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,
ich vermute den Fehler in der Behandlung der Sonderzeichen und den Encodings.

byte[] bytearry = enc.GetBytes(data);

Was ist hier data? Wenns ein System.String ist, wäre Unicode das richtige Encoding.
Damit und auch mit UTF-8 erhältst Du aber ggf. mehrere bytes je Zeichen, und das interpretieren eines einzelnen byte als Zeichen führt zwangsläufig zu Fehlern. Danach ist Dein Text vermutlich kein wohlgeformtes XML mehr...

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

U
1.688 Beiträge seit 2007
vor 13 Jahren

Hallo,

ergänzend zum bisherigen: Strings können nicht "zerstört" werden, da sie unveränderlich sind. Außerdem mutet Dein Convert.ToString auf einen String angewandt sehr merkwürdig an.

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

Danke!

Exception ist:
Message = "Unerwartetes Ende der Datei bei der Syntaxanalyse von Name. Zeile 1, Position 683."
Source System.Xml

Unicode geht leider gar nicht, da wird mir der komplette String zerrissen.
Im Header der XML steht außerdem UTF8.

In der XML befinden sich ab und zu Steuerzeichen diese müssen entfernt werden, sonst stürzt das
XMLLoad andauert ab.

Nach dem raußwerfen der Bytes unter 32 und über 126 kann der String noch ausgegeben werden
und sieht so aus wie er aussehen soll.

Es ist mir absolut unverständlich wie das passieren kann ....

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,

ich kann mich nur wiederholen: Ein String ist immer 16bit Unicode. Wenn data an der von mir genannten Stelle bereits als String vorliegt, müsste vorher das byte[], das Du vom Netzwerk bekommst, mit UTF-8 zu diesem String gemacht worden sein.

Nach dem raußwerfen der Bytes unter 32 und über 126 kann der String noch ausgegeben werden was nicht verwunderlich ist, da Du dann ja nur noch Low-ASCII-Zeichen hast.
und sieht so aus wie er aussehen soll. bist Du Dir da sicher? Und handelt es sich eigentlich wirklich um Steuerzeichen, oder um Zeichen die Du nicht zuordnen kannst -> das könnte auch am Encoding im Multibyte-Format liegen.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

bist Du Dir da sicher?

Also wenn ich ihn auf die konsole ausgeben sieht man ne unformatierte xml.
Wird diese dann in das xmlDocument gesteckt fehlt auf einmal die hälfte.
Was ich sehr schwer verstehen kann da:

Du dann ja nur noch Low-ASCII-Zeichen hast.

Die XML hat hier einen Header der besteht aus 12Bytes irgendwas ... zb. würde das erste Byte
0000 0011 einfach die Zahl 3 beteuten ....

Normalerweiße müsste es reichen:

data = data.Remove(0, data.IndexOf("<?xml"));

leider bringt das nix ...

Außerdem mutet Dein Convert.ToString auf einen String angewandt sehr merkwürdig an.

Ich will hier sicher gehen das hinten ein NULL byte dran hängt, da +="\0" nicht funktioniert.
Ich könnte höchstens noch versuchen die NULL bytes drinnen zu lassen

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,

müsste vorher das byte[], das Du vom Netzwerk bekommst, mit UTF-8 zu diesem String gemacht worden sein

Das ist die Vorgehensweise, an die Du Dich erst mal halten musst. Das heisst, Du musst mit Encoding.GetString die vom Netz kommenden Daten, die Du ja vermutlich als byte[] empfängst, als UTF-8 dekodieren. Dann hast Du einen vernünftigen Unicode-String.
Wenn Du ein vollwertiges XML-Dokument bekommst , ist zweifelhaft, ob dann noch Bereinigungsarbeiten nötig sind. Normalerweise müsstest Du den String dann direkt nutzen können.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

U
1.688 Beiträge seit 2007
vor 13 Jahren

Hallo,

schreibe mal die über TCP empfangenen Daten ohne Änderungen in eine Datei. Wenn Du einen Fehler bekommst, kannst Du die dann zuletzt gespeicherte Datei mal posten. Alles andere artet in Raterei aus.

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

das ist mein Tcp receive:


Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);

if (recv > 0)
{
  client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
  //alles was kleiner ist als 14 bytes wird nicht beachtet
  if (recv > 14)
  {
    string stringData = Encoding.ASCII.GetString(data, 0, recv);
...
}}....

wollt ihr das byte array sehen oder schon den string(den ja console.writeline korrekt ausgeben kann)?

U
1.688 Beiträge seit 2007
vor 13 Jahren

wollt ihr das byte array sehen oder schon den string

Eher eine Datei, in die das Byte-Array geschrieben wurde.

string stringData = Encoding.ASCII.GetString(data, 0, recv);

sieht auch nicht unbedingt gut aus, wenn es sich um Unicode handelt. Und auch nicht, wenn es teilweise Binärdaten sind.

5.299 Beiträge seit 2008
vor 13 Jahren

wenn der sender korrektes xml schickt, solls auch wohl ankommen. Deine "Bereinigung" scheint mir abenteuerlich. V.a. wird da Encoding.UTF8 verwendet, und beim TCP-Empfang Ascii.

Das Xml mal zu posten wurde ja schon angefragt.

Der frühe Apfel fängt den Wurm.

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

Ich habe natürlich auch schon probiert UTF8 zu encoden ... selbes problem ...

So hier nun ein Screenshot darin sieht man:
Der komplette String kann(und wird zuerst) in die Datei geschreiben, sieht man auch im editor.
Danach ist der String schon nur mehr halb da, man sieht in der Konsole das ein Teil davon fehlt...
Und dann stürzt natürlich xmlDocument ab....

Wenn ich die Funktion für das schreiben in die Datei auskommentiere, zeigt die Konsole wieder den kompletten string an.

Wir hingegen der String erst nach der Ausgabe in der Konsole in dei Datei geschreiben, fehlt in der Datei die hälfte ....

Unglaublich... und unmöglich...

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

Das da oben sei mal dahingestellt ...

Allerdings ist mir nun aufgefallen das das receiveData event bei mir mehrfach ausgelöst wird. Dh. bei TCP kommt etwas an ich löse das event aus und die methode einer anderes Klasse die es Abboniert hat bekommts bis zu 3 mal...

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

Nun hab ich das Probiert und ein Bild davon gemacht sonst glaubts mir keiner ....

Nich die ganze Methode wird mehrfach ausgeführt, es werden anscheinen einzelene Codezeilen mehrfach ausgeführt o.O

Die methode checkDate enthällt kein Console.writeline mehr, sieht man auch wenn man den vorhergehenden Output anschaut ....
"Bekomme daten" und "string.len" taucht nur einmal auf.

U
1.688 Beiträge seit 2007
vor 13 Jahren

Hallo,

ich vermute Multithreading-Probleme. Was ist z. B. mit dem String data? Der wird oben mal in Receive, mal in der Auswertung benutzt. Ist das das selbe? Oder heißen die nur gleich?

Auch die "Mehrfachausführung" kann damit zusammenhängen. Oder Du abonnierst das Ereignis mehrfach.

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

Die oberste Funktion ist receiveDate auf diese ist das Event abboniert.
Mein String kommt von xmlInfo.Xml, wird dann in xml.checkData übergeben dort heißt er
dann "data".

Das Event wurde nur einmal hinzugefügt, aber gibt es hier eine Möglichkeit sicherzustellen
das es nur einmal abboniert ist?

MANCHMAL wird receiveDate mehrfach ausgelöst und zwar genau 3 mal(o.O) in 90% der fälle wird es aber nur
einmal ausgelöst, so wie es sein soll.
Wenn diese 3 mal ausgelöst werden kommt es vor das ein xmlInfo.xml nicht komplett ist(also ein Teil fehlt)
die anderne beiden sind meist in Ordnung(einer davon sicher).
Anscheinend werden wärend der verarbeitung diese beiden Strings vertauscht oder was auch immer,
und dann ist von einem auf dem anderen Moment ein anderer String an dieser Speicheradresse bzw
die Speicheradresse wird vertauscht.

Das Programm läuft selbstverständlich, da ja eine xml immer korrekt ist ...

Gelöschter Account
vor 13 Jahren

und dann ist von einem auf dem anderen Moment ein anderer String an dieser Speicheradresse bzw
die Speicheradresse wird vertauscht.

sowas geht in .net nur mit viel viel mühe.... jedoch sicherlich nciht in deinem szenario.

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

tja mir fällt keine bessere Erklärung ein ...

Gelöschter Account
vor 13 Jahren

mach doch mal ein "short but complete" projekt, das lauffähig ist und wo man diesen fehler nachvollziehen kann. dann kann ich oder auch andere mal durchdebuggen.

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

Danke euch.

Ich hab das ganze mal an ner anderen Anlage in nem anderen Netzwerk getestet, da liefs ohne diesen Fehler, warum auch immer...

Diese Problem verursacht (momentan) keine Fehler, daher ist das
ganze für mich abgeschlossen.

Sollte in Zukunft allerdings fehler auftreten, wird mir wohl nix anderes übrig bleiben als
die Komponente auszubaun und im detail zu testen,
dann werd ich mich sicher wieder
mal Melden, danke 😉

Gelöschter Account
vor 13 Jahren

du lässt einen reproduzierbaren fehler auf ein produktivsystem los, in der hoffnung, das es dennoch gut geht?

D
diego2k Themenstarter:in
99 Beiträge seit 2008
vor 13 Jahren

is von höherer stelle so entschieden 😉 ... abgesehn davon gehts eh
immer gut(oben beschrieben)

U
1.688 Beiträge seit 2007
vor 13 Jahren
D
19 Beiträge seit 2008
vor 13 Jahren

Auch auf die Gefahr hin, dass ich gleich gesteinigt werde so einen alten Thread wieder aufzureissen.
ich habe hier die gleiche Fehlermeldung erhalten "unerwartetes ende der datei bei der Syntaxüberprüfung..."

Google hat diesen Thread als einzig vernünftig verwertbaren ausgespuckt und deshalb möchte ich hier meine Lösung noch reinschreiben.

Bei mir war das Problem, dass ich den Deserializer mit einem Stream gefüttert hatte, der noch nicht weit genug geschrieben war.

stream.write(...);
Deserialize....

es hat ledeglich ein stream.flush zwischen den zeilen gefehlt