2009-05-16 24 views
13

Bitte, was ist eine gute Möglichkeit, wirklich große XML-Dokumente (bis zu 500 MB) in C# .NET 3.5 zu schreiben? Ich habe ein bisschen herumgesucht und finde anscheinend nichts, was diese spezifische Frage angeht.Wie schreibe ich (groß) XML in eine Datei in C#?

Mein vorheriger Thread (What is the best way to parse (big) XML in C# Code?) abgedeckt lesen ähnliche Magnitude Xml Dokumente ... Damit gelöst, muss ich darüber nachdenken, wie die aktualisierten Funktionen (http://www.opengeospatial.org/standards/sfa) in ein "update.xml" Dokument zu schreiben.

Meine Ideen: Offensichtlich ein großes DOM ist out, unter Berücksichtigung der maximalen Größe des Dokuments zu produzieren. Ich benutze XSD.EXE, um bindende Klassen aus dem Schema zu generieren ... was gut mit der XmlSerializer-Klasse zusammenpasst, aber ich denke, es baut ein DOM "unter der Haube". Ist das richtig?. Ich kann nicht alle Funktionen (bis zu 50.000) gleichzeitig im Speicher halten. Ich muss ein Feature aus der Datenbank lesen, serialisieren und in eine Datei schreiben. Ich denke, ich sollte den XmlSerializer verwenden, um ein "Doclet" für jedes einzelne Feature in die Datei zu schreiben. Ich habe (noch) keine Ahnung, ob das überhaupt möglich ist.

Was denkst du?

Hintergrund: Ich portiere ein altes VB6 MapInfo "Client-Plugin" zu C#. Es existiert ein J2EE "Update Service" (eigentlich nur eine Web-App) mit dem dieses Programm (ua) arbeiten muss. Ich kann den Server nicht ändern; es sei denn, es ist absolut notwendig; Dazu gehört insbesondere die Änderung der anderen Kunden. Der Server akzeptiert ein XML-Dokument mit einem Schema, das keine Namespaces definiert ... dh es gibt nur den Standard-Namespace, und alles ist darin enthalten.

Meine Erfahrung: Ich bin so ziemlich ein C# und .NET-Neuling. Ich programmiere seit ungefähr 10 Jahren in verschiedenen Sprachen einschließlich Java, VB, C und C++.

Prost alle. Keith.

PS: Es ist Abendessen Zeit, so werde ich für etwa eine halbe Stunde AWOL sein.

Antwort

16

Zum Schreiben von großen xml, XmlWriter (direkt) ist dein Freund - aber es ist schwieriger zu bedienen. Die andere Möglichkeit wäre, DOM/Objekt-Modellansätze zu nutzen und kombinieren sie, was wahrscheinlich machbar ist, wenn Sie die Kontrolle über die XmlWriterSettings ergreifen und den XML-Marker deaktivieren, und würden die Namespace-Deklarationen zu befreien ...

using System; 
using System.Collections.Generic; 
using System.Xml; 
using System.Xml.Serialization;  
public class Foo { 
    [XmlAttribute] 
    public int Id { get; set; } 
    public string Bar { get; set; } 
} 
static class Program { 
    [STAThread] 
    static void Main() { 
     using (XmlWriter xw = XmlWriter.Create("out.xml")) { 
      xw.WriteStartElement("xml"); 
      XmlSerializer ser = new XmlSerializer(typeof(Foo)); 
      XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
      ns.Add("",""); 
      foreach (Foo foo in FooGenerator()) { 
       ser.Serialize(xw, foo, ns); 
      } 
      xw.WriteEndElement(); 
     } 
    }  
    // streaming approach; only have the smallest amount of program 
    // data in memory at once - in this case, only a single `Foo` is 
    // ever in use at a time 
    static IEnumerable<Foo> FooGenerator() { 
     for (int i = 0; i < 40; i++) { 
      yield return new Foo { Id = i, Bar = "Foo " + i }; 
     } 
    } 
} 
+0

Marc, Merci. (Nach meinem Kommentar zu David Schmitts Antwort) Ich werde es auf beide Arten versuchen und einige Leistungstests durchführen. Ich danke Ihnen, Sir, für Ihre nachdenkliche Antwort und diesen Beispielcode. Genial. Ta. ;-) Ich hoffe nur, dass ich die Gunst eines Tages zurückzahlen kann. Prost. Keith. – corlettk

-1

Warum nicht einfach einen TextWriter verwenden, um das XML zu schreiben?

+0

Weil XML kein Text ist. –

+5

"...nicht * einfach * text. ";-) – Cerebrus

+0

Überhaupt nicht. Siehe das XML Infoset Zeug (http://www.w3.org/TR/xml-infoset/). Verwechseln Sie die Daten nicht mit ihrer Darstellung. –

9

Verwenden Sie ein XmlWriter:

[...] ein Schriftsteller, die eine schnelle, nicht zwischengespeichert, Vorwärts-Mittel von Erzeugungs Streams oder Dateien mit XML-Daten.

+0

Spot auf Ziel! +1 – Cerebrus

+0

OK Ich werde beide Möglichkeiten versuchen (nur für die Schlüsselelemente, um Zeit zu sparen) in einem Prototyp. XmlWriter sieht aus wie " die richtige Antwort ", aber ich denke, es wird viel mehr Code als meine ursprüngliche XmlSerializer-Lösung beinhalten, und hebt auch th auf e "Flexibilität" Vorteile der Verwendung von generierten Bindungsklassen ... weil der handgemachte Schreibcode alles über das genaue Schema wissen muss. Ich danke Ihnen für Ihre Zeit ... Prost. Keith. – corlettk

1

Haben Sie darüber nachgedacht, es zu komprimieren, bevor Sie es auf die Festplatte schreiben? Mit XML können Sie mehr als 10 mal komprimieren und noch mehr erreichen. Es wird wahrscheinlich weniger Zeit brauchen, um die Datei zu komprimieren und die komprimierte Version zu schreiben, als die gesamte 500Mb-Version zu lesen.

+1

Das größere Problem ist, dass die In-Memory-DOM-Repräsentation in der Regel> x10 des eigentlichen zugrunde liegenden XML ist ... und 5Gb ist einfach zu groß, um vernünftig zu handhaben. Und wieder hilft es nicht, wenn es eine existierende API/Erwartung einer unkomprimierten Datei gibt. –

+0

Es ist ein guter Gedanke. Vielen Dank. Ich kann es auch komprimieren, bevor es auf die Platte trifft; Speichern Sie etwas Zeit (und Speicher), lesen Sie es zurück und senden Sie es als HttpWebRequest. Unsere Erfahrung mit dieser XML-Datei wird auf etwa ein Viertel der explodierten Größe komprimiert ... (3/4) * 500 = 375 MB RAM. – corlettk

Verwandte Themen