Laden...

[erledigt] XmlSerializer erstellt manchmal fehlerhafte Datei?

Erstellt von MillionsterNutzer vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.448 Views
M
MillionsterNutzer Themenstarter:in
235 Beiträge seit 2005
vor 10 Jahren
[erledigt] XmlSerializer erstellt manchmal fehlerhafte Datei?

Hallo zusammen,

Ich schreibe die Einstellungen für ein kleines WPF-Tool in eine XMl-Datei. Dazu nutze ich den System.Xml.Serialization.XmlSerializer. In der Regel funktioniert das auch wie gewohnt allerdings hatte ich nun schon ein paar wenige male den Fall dass die erstellte Datei anschließend nicht mehr gelesen werden konnte. Bei genauerer Prüfung fiel mir dann immer auf das am Ende der Datei irgendeine halblebige Wiederholung dran hängt die da nicht sein dürfte.

Das original File sollte so aussehen:


<?xml version="1.0"?>
<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <WebServiceURL>http://apper01:8999/SkriptWebService</WebServiceURL>
  <LogLevel>2</LogLevel>
  <UserLanguage>de</UserLanguage>
</Settings>

Bei fehlerhaten Fall wird dann immer ein Teil von dem schließenden Settings-Tag wiederholt. Also so:


<?xml version="1.0"?>
<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <WebServiceURL>http://apper01:8999/SkriptWebService</WebServiceURL>
  <LogLevel>2</LogLevel>
  <UserLanguage>de</UserLanguage>
</Settings>s>

Ich hatte bisher noch nie Probleme mit dem XMLSerializer und frage mich woher das kommt. Im Netz scheint es so als ob ich der Einzige wäre der das Problem je hatte. Leider tritt das Problem nur sporadisch auf so dass ich es nicht wirklich reproduzieren kann. Auch wundert mich das an der Datei "zuviel" dran ist - Ich hätte es für wahrscheinlicher gehalten dass etwas fehlt.

Hat jemand von euch eine Idee woran es liegen könnte?

Viele Grüße

Ralf

A
764 Beiträge seit 2007
vor 10 Jahren

Hallo Ralf,

das im XmlSerializer ein bug ist (zumindest so einer) halte ich erst mal für unwahrscheinlich. Der wird soviel benutzt, das wäre doch schon aufgefallen. Da es nur sporadisch auftritt, könnte ich mir vorstellen, dass ein threading-problem vorliegt. Möglicherweise versucht er gleichzeitig zwei mal in die Xml-Datei zu serialisieren.

Gruß, Alf

6.911 Beiträge seit 2009
vor 10 Jahren

Hallo MillionsterNutzer,

zeig mal den Code wo und wie du serialisiert.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

M
MillionsterNutzer Themenstarter:in
235 Beiträge seit 2005
vor 10 Jahren

Hi Alf,

das mit dem Threadingproblem habe ich kurz gecheckt. Eigentlich dürft das nicht der Fall sein, da der XMLSerializer zum schreiben das File ja sicher explizit für sich beansprucht - ein zweiter Thread dürfte dann ja nicht ran.

Ich habe daher mal eben mit dem Speichern der Settings rumgespielt und kann das Problem jetzt reproduzieren:
Ich habe den Verbindungsstring von apper01 auf localhost umgestellt und umgekehrt. die beiden Angaben sind ja nicht gleich lang: Localhost ist zwei zeichen länger und der Mist der am Ende der Dateo angehängt wird ist auch zwei Zeichen lang. Wenn ich also nun eine Datei mit kürzerem Inhalt abspeichere tritt das Problem auf.

Ich hab zum Test mal eben ein lock um den XMLSerializer und das .Serialize() drumrum gemacht - das ändert nichts an dem Verhalten. Auch wird der Block beim Debuggen nur einmal aufgerufen. Ich unterstelle also mal dass das Problem doch nicht im Threadingbereich liegt.

Noch eine Idee?

hier der Code...


            try
            {

                lock (this)
                {
                    if (!di.Exists)
                    {
                        di.Create();
                    }

                    if (!fi.Exists)
                    {
                        fs = fi.Create();
                    }

                    if (fs == null)
                    {
                        fs = new FileStream(fi.FullName, FileMode.Open);
                    }

                    XmlSerializer xs = new XmlSerializer(typeof(Settings));
                    xs.Serialize(fs, this);
                }
            }

6.911 Beiträge seit 2009
vor 10 Jahren

Hallo MillionsterNutzer,

wenn dann beim nächsten Aufruf die Datei bereits existiert (fi.Exists), dann wird der gleiche FileStream verwendet. Da liegt dieses Verhalten schon fast auf der Hand. Erstell den FileStream jedesmal vor dem Serialisieren neu und gut.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

S
417 Beiträge seit 2008
vor 10 Jahren

Erstell den FileStream jedesmal vor dem Serialisieren neu und gut.

Eben. Aber wenn dann nutze auch FileMode.Create und nicht FileMode.Open.

M
MillionsterNutzer Themenstarter:in
235 Beiträge seit 2005
vor 10 Jahren

Hallo Sarc, hallo gfoidl,

ihr habt Recht: Es liegt am FileStream. So wie es aussieht reicht es einfach schon aus von FileMode.Open auf FileMode.Create umzustellen und das Problem ist behoben.
Ich war mir nicht bewusst das FileMode.Open hier ungeeignet ist. So wie ich das verstehe sollte FileMode.Open nur beim Lesen oder beim gezielten beschreiben der Datei verwendet werden. Ich möchte ja in meinem Fall die alte Settingsdatei komplett durch eine neue ersetzen, also bietet sich hier FileMode.Create an.

Ob ich mir das bis zum nächsten mal merken kann 😒

Vielen Dank an alle!!!

6.911 Beiträge seit 2009
vor 10 Jahren

Hallo MillionsterNutzer,

reicht es einfach schon aus von FileMode.Open auf FileMode.Create umzustellen

Aber nicht für Folgeaufrufe, zumindest nicht nach dem Snippet das du oben gezeigt hast. Beim 2. Aufruf wird der alte FileStream verwendet (fi.Exist = true & fs != null). Das musst du auch abändern und lässt sich mit dem Debugger (siehe auch [Artikel] Wie verwende ich den Debugger von Visual Studio?) leicht überprüfen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

M
MillionsterNutzer Themenstarter:in
235 Beiträge seit 2005
vor 10 Jahren

Hallo gfoidl,

du hättest unter Umständen Recht, aber ich hab dummerweise nicht den ganzen Code sondern nur ein kleines Snipped gezeigt. Tatsächlich kommt darüber nur noch die Variablendeklaration und darunter noch ein wenig Errorhandling, dann ist die Methode komplett. Die Variable fs für den FileStream ist lokal und wird daher bei jedem Aufruf der Methode erst mal null sein, d.h. es wird jedesmal ein neuer FileStream generiert.

Ich hättes etwas mehr Code posten sollen, sorry.

Viele Grüße

Ralf