2009-05-16 20 views
13

Gente,¿Cómo escribir XML (grande) en un archivo en C#?

Por favor, ¿cuál es una buena forma de escribir documentos XML muy grandes (hasta 500 MB) en C# .NET 3.5? He tenido un poco de búsqueda, y parece que no puedo encontrar nada que aborde esta pregunta específica.

Mi hilo anterior (What is the best way to parse (big) XML in C# Code?) cubierto leyendo documentos de magnitud similar Xml ... Con eso resuelto, tengo que pensar en cómo escribir las características actualizadas (http://www.opengeospatial.org/standards/sfa) en un documento "update.xml".

Mis ideas: Obviamente, se ha eliminado un gran DOM, teniendo en cuenta el tamaño máximo del documento que se va a producir. Estoy usando XSD.EXE para generar clases de enlace desde el esquema ... que funciona muy bien con la clase XmlSerializer, pero creo que construye un DOM "bajo el capó". ¿Es esto correcto?. No puedo mantener todas las funciones (hasta 50,000 de ellas) en la memoria al mismo tiempo. Necesito leer una característica de la base de datos, serializarla y escribirla en un archivo. Así que estoy pensando que debería usar XmlSerializer para escribir un "doclet" para cada característica individual en el archivo. Todavía no tengo idea (todavía) si esto es posible/factible.

¿Qué opinas?

Antecedentes: Estoy portando un viejo VB6 MapInfo "cliente complemento" a C#. Existe un "servicio de actualización" de J2EE (en realidad solo una aplicación web) con el que debe trabajar este programa (entre otros). No puedo cambiar el servidor; a menos que sea absapositivamente necesario; especialmente de eso implica cambiar a los otros clientes. El servidor acepta un documento XML con un esquema que no especifica ningún espacio de nombres ... es decir: solo hay espacio de nombres predeterminado, y todo está en él.

Mi experiencia: Soy casi un C# y .NET novato. He estado programando durante aproximadamente 10 años en varios idiomas, incluidos Java, VB, C y algunos C++.

Saludos a todos. Keith.

PD: Es la hora de la cena, así que estaré ausente durante aproximadamente media hora.

Respuesta

16

Para escribir xml grande, XmlWriter (directamente) es su amigo, pero es más difícil de usar. La otra opción sería utilizar enfoques DOM/objeto-modelo y combinarlas, que es probablemente factible si que tomar el control del XmlWriterSettings y desactivar el marcador de XML, y deshacerse de las declaraciones de espacios de ...

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. (Según mi comentario a la respuesta de David Schmitt) Lo intentaré de ambas formas y realizaré algunas pruebas de rendimiento. Le agradezco señor por su respuesta, y ese código de ejemplo. Increíble. Ejército de reserva. ;-) Solo espero poder devolver el favor algún día. Saludos. Keith. – corlettk

-1

¿Por qué no simplemente usar un TextWriter para escribir el XML?

+0

Porque XML no es texto. –

+5

"...no * simplemente * texto. ";-) – Cerebrus

+0

No, en absoluto. Consulte el material XML Infoset (http://www.w3.org/TR/xml-infoset/). No confunda los datos con su representación. –

9

Utilice un XmlWriter:

[...] un escritor que proporciona una forma rápida, sin almacenamiento en caché, sólo avance medio de corrientes generadoras o archivos que contienen datos XML .

+0

Puntualo en el objetivo! +1 – Cerebrus

+0

Bien, intentaré en ambos sentidos (solo para los elementos clave, para ahorrar tiempo) en un prototipo. XmlWriter se ve como " la respuesta correcta ", pero supongo que implicará MUCHO más código que mi solución inicial XmlSerializer, y también anula Los beneficios de "flexibilidad" del uso de clases de enlace generadas ... porque el código de escritura hecho a mano debe conocer todo sobre el esquema exacto. Gracias por su tiempo ... Saludos. Keith. – corlettk

1

¿Consideró comprimirlo antes de escribirlo en el disco? Con XML puede llegar a comprimirse más de 10 veces y aún más. probablemente le tomará menos tiempo comprimir el archivo y escribir la versión comprimida que leer toda la versión de 500Mb.

+1

El problema más grande es que la representación DOM en la memoria suele ser> x10 del xml subyacente real ... y 5Gb es demasiado grande para manejar de forma sensata. Y nuevamente, no ayuda si existe una API/expectativa de un archivo descomprimido. –

+0

Es una buena idea. Gracias. También puedo comprimirlo antes de que llegue al disco; ahorrando tiempo (y memoria) leyéndolo y enviándolo como HttpWebRequest. Nuestra experiencia con este XML se comprime a aproximadamente una cuarta parte de su tamaño de explosión ... ahorro (3/4) * 500 = 375 MB de RAM. – corlettk

Cuestiones relacionadas