Serializar objetos en XML (XmlSerialization, XDocument, XmlWriter, etc)

Iniciado por GonzaFz, 1 Marzo 2017, 00:42 AM

0 Miembros y 1 Visitante están viendo este tema.

GonzaFz

Estoy escribiendo un Packet Sniffer y lo que quiero hacer es cada vez que capturo un paquete, serializarlo a un archivo XML para poder procesarlo mas tarde.

Estuve analizando usar XmlSerialization que fue lo primero que encontre en google pero mi problema es que, por lo que vi, esta pensado para que cada vez que se serializa un objeto, este se guarde en un nuevo archivo (lo digo por el hecho de que escribe el archivo completo, incluyendo el namespace y etc). Si utilizo esto lo que ocurre es que tengo que mantener en memoria todos los paquetes que vayan llegando hasta que el usuario quiera dejar de capturar y luego recien escribir el archivo (uso excesivo de memoria).

Mi primera idea fue que cada vez que llegue un paquete, escribirlo en el archivo y liberar ese objeto, por lo que me parece que XDocument puede ser util en este caso, solo que voy a tener que escribir manualmente el proceso de serialización.

Basicamente lo que me gustaria saber, si ya manejaron la serialización xml, como me recomiendan haga este proceso.

Saludos

Eleкtro

Hola. Si el problema es que quieres serializar varios elementos del mismo tipo y en un mismo archivo, entonces serializa una colección de elementos, por ejemplo la colección genérica y serializable List(Of T).

Ejemplo con un tipo personalizado:

Código (vbnet) [Seleccionar]
<Serializable>
<XmlRoot("PacketInfo")>
Public Class PacketInfo ' : Implements IXmlSerializable

   <XmlElement("Value")>
   Public Property Value As String

   Public Sub New()
   End Sub

   Public Sub New(ByVal value As String)
       Me.Value = value
   End Sub

End Class


+

Código (vbnet) [Seleccionar]
Dim piList As New List(Of PacketInfo)
Dim pi1 As New PacketInfo("value1")
Dim pi2 As New PacketInfo("value2")
piList.AddRange({pi1, pi2})

' Serialize
Dim sr As New XmlSerializer(GetType(List(Of PacketInfo)), {GetType(PacketInfo)})
Using fs As New FileStream("Packets.xml", FileMode.Create)
   sr.Serialize(fs, piList)
End Using

' Deserialize
piList.Clear()
Using fs As New FileStream("Packets.xml", FileMode.Open)
   piList = DirectCast(sr.Deserialize(fs), List(Of PacketInfo))
End Using

sr.Serialize(Console.Out, piList)


¡Saludos!








dato000

Te dejo un ejemplo con c# que encontre en http://stackoverflow.com/questions/364253/how-to-deserialize-xml-document

Primero se usa un modelo, en el modelo se tiene que especificar los atributos de las propiedades, y deben ser atributos del tipo XML.


Here are the classes:

Código (csharp) [Seleccionar]
[Serializable()]
public class Car
{
    [System.Xml.Serialization.XmlElement("StockNumber")]
    public string StockNumber { get; set; }

    [System.Xml.Serialization.XmlElement("Make")]
    public string Make { get; set; }

    [System.Xml.Serialization.XmlElement("Model")]
    public string Model { get; set; }
}


[Serializable()]
[System.Xml.Serialization.XmlRoot("CarCollection")]
public class CarCollection
{
    [XmlArray("Cars")]
    [XmlArrayItem("Car", typeof(Car))]
    public Car[] Car { get; set; }
}



La funcion de deserizalizar y poder manejar las variables dentro de un streamreader, es decir, un string.

Código (csharp) [Seleccionar]
CarCollection cars = null;
string path = "cars.xml";

XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));

StreamReader reader = new StreamReader(path);
cars = (CarCollection)serializer.Deserialize(reader);
reader.Close();



Y bueno, también es necesario utilizar bien la codificación correcta para tu paquete XML.

Código (csharp) [Seleccionar]
<?xml version="1.0" encoding="utf-8"?>
<CarCollection>
<Cars>
  <Car>
    <StockNumber>1020</StockNumber>
    <Make>Nissan</Make>
    <Model>Sentra</Model>
  </Car>
  <Car>
    <StockNumber>1010</StockNumber>
    <Make>Toyota</Make>
    <Model>Corolla</Model>
  </Car>
  <Car>
    <StockNumber>1111</StockNumber>
    <Make>Honda</Make>
    <Model>Accord</Model>
  </Car>
</Cars>
</CarCollection>



Slds



GonzaFz

Hola, gracias a los dos por responder.

Entiendo la idea que me plantean, es basicamente como hice mi solución actual (aunque en un futuro me gustaria cambiar).
El problema es que yo estoy haciendo un packet sniffer, y para usar esta idea tengo que mantener una lista con todos los paquetes hasta que el usuario decida terminar el programa.
No pasara nada si son unos minutos, pero si se deja mucho tiempo el uso de memoria seria excesivo e ineficiente (porque no hay razon de tener todos los paquetes en memoria cuando la idea es simplemente escribirlos a un archivo).

Es decir que lo que quiero lograr es que cada vez que se envie o reciba un paquete, escribirlo en un archivo y olvidarme de el.


Entiendo que esto lo puedo hacer manualmente con XDocument pero me interesa saber si no me estaré pasando por alto algo o mi idea de que la lista ocupara mucha memoria es erronea, ya que no soy de programar mucho.