2009-06-04 15 views
1

Ich habe den folgenden Code:Serialisierung und Deserialisierung in eine XML-Datei, C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 

namespace ConsoleApplication28 
{ 
class Program 
{ 

    static void Main() 
    { 
     List<string> dirs = FileHelper.GetFilesRecursive(@"c:\Documents and Settings\bob.smith\Desktop\Test"); 
     foreach (string p in dirs) 
     { 
      Console.WriteLine(p); 
     } 

     //Write Count 
     Console.WriteLine("Count: {0}", dirs.Count); 
     Console.Read(); 

    } 

    static class FileHelper 
    { 
     public static List<string> GetFilesRecursive(string b) 
     { 
      // 1. 
      // Store results in the file results list. 
      List<string> result = new List<string>(); 

      // 2. 
      // Store a stack of our directories. 
      Stack<string> stack = new Stack<string>(); 

      // 3. 
      // Add initial directory. 
      stack.Push(b); 

      // 4. 
      // Continue while there are directories to process 
      while (stack.Count > 0) 
      { 
       // A. 
       // Get top directory 
       string dir = stack.Pop(); 

       try 
       { 
        // B 
        // Add all files at this directory to the result List. 
        result.AddRange(Directory.GetFiles(dir, "*.*")); 

        // C 
        // Add all directories at this directory. 
        foreach (string dn in Directory.GetDirectories(dir)) 
        { 
         stack.Push(dn); 
        } 
       } 
       catch 
       { 
        // D 
        // Could not open the directory 
       } 
      } 
      return result; 
     } 
    } 
} 
} 

Der obige Code funktioniert gut für rekursiv zu finden, welche Dateien/Verzeichnisse in einem Ordner auf meinem c liegen :.
Ich versuche, die Ergebnisse dessen, was dieser Code mit einer XML-Datei macht, zu serialisieren, aber ich bin nicht sicher, wie dies zu tun ist.

Mein Projekt ist das: Finden Sie alle Dateien/Verzeichnisse w/in einem Laufwerk, Serialisierung in eine XML-Datei. Dann, beim zweiten Mal, wenn ich diese App starte, habe ich zwei XML-Dateien zum Vergleich. Ich möchte dann die XML-Datei vom ersten Mal, wenn ich diese App ausführte, deserialisieren und Unterschiede mit der aktuellen XML-Datei vergleichen und einen Bericht über Änderungen erstellen (d. H. Dateien, die hinzugefügt, gelöscht, aktualisiert wurden).

Ich hatte gehofft, etwas Hilfe zu bekommen, da ich ein Anfänger in C# bin, und ich bin sehr sehr wackelig auf Serialisierung und Deserialisierung. Ich habe viel Mühe beim Programmieren. Kann mir jemand helfen?

Danke

Antwort

3

Ihr Ergebnis ist List<string> und das ist nicht direkt serialisierbar. Sie werden es wickeln müssen, einen minimalen Ansatz:

[Serializable] 
class Filelist: List<string> { } 

Und dann die (De) Serialisierung geht so:

Filelist data = new Filelist(); // replaces List<string> 

// fill it 

using (var stream = File.Create(@".\data.xml")) 
{ 
    var formatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter(); 
    formatter.Serialize(stream, data); 
}  

data = null; // lose it 

using (var stream = File.OpenRead(@".\data.xml")) 
{ 
    var formatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter(); 
    data = (Filelist) formatter.Deserialize(stream); 
} 

Aber beachten Sie, dass Sie nicht die XML in irgendeiner Weise werden zu vergleichen (nicht praktisch). Sie werden (deserialzed) List-Instanzen vergleichen. Und das XML ist SOAP-formatiert, sieh es dir an. Es kann in einem anderen Kontext nicht sehr nützlich sein.

Und daher könnte man leicht einen anderen Formatter verwenden (binary ist ein bisschen effizienter und flexibler).

Oder vielleicht möchten Sie nur persist die Liste der Dateien als XML. Das ist eine andere Frage.

0

Hilfe # 1. Code um vier Leerzeichen einrücken, damit er als Code angezeigt wird, wenn Sie hier posten.

2: loswerden dieser Versuch/catch-Block, wie es essen wird alle Ausnahmen, einschließlich derjenigen, die Sie wissen möchten.

3: Haben Sie überhaupt versucht, Ihre Ergebnisse zu serialisieren? Bitte bearbeiten Sie Ihre Frage, um zu zeigen, was Sie versucht haben. Tipp: Verwenden Sie die XmlSerializer-Klasse.

+0

Nun, die Sache ist, ich bin nicht klar, wie die XMLSerializer-Klasse genau zu implementieren. Ich mache jetzt C# seit 3 ​​Monaten ... und ich habe große Lücken in meinem Wissen. Ich habe Beispiele verfolgt, die ich im Internet gefunden habe, aber ich habe keine Ahnung, wie ich das Beispiel verwenden würde, um mir hier zu helfen ... und wo ich den Code selbst einfügen könnte. – yeahumok

+0

@yeahumok: Vielleicht möchten Sie überlegen, ob "das Finden von Beispielen" der richtige Weg für Sie ist, zu lernen. Manche Menschen lernen auf diese unstrukturierte Art gut. Andere verlangen jemanden, der die Struktur des Wissens bereits kennt, um es in einer vernünftigen Ordnung darzustellen. Vielleicht brauchen Sie das. Vielleicht würde etwas wie http://msdn.microsoft.com/en-us/library/90c86ass(VS.85).aspx Ihnen helfen, und nicht zufällige Beispiele, die Sie zufällig finden. –

1

Diese Klasse serialisiert und deserialisiert sich selbst .... hoffentlich hilft das.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Xml.Serialization; 
using System.Xml; 

namespace TestStuff 
{ 
    public class Configuration 
    { 
     #region properties 

     public List<string> UIComponents { get; set; } 
     public List<string> Settings { get; set; } 

     #endregion 

     //serialize itself 
     public string Serialize() 
     { 
      MemoryStream memoryStream = new MemoryStream(); 

      XmlSerializer xs = new XmlSerializer(typeof(Configuration)); 
      using (StreamWriter xmlTextWriter = new StreamWriter(memoryStream)) 
      { 
       xs.Serialize(xmlTextWriter, this); 
       xmlTextWriter.Flush(); 
       //xmlTextWriter.Close(); 
       memoryStream = (MemoryStream)xmlTextWriter.BaseStream; 
       memoryStream.Seek(0, SeekOrigin.Begin); 
       StreamReader reader = new StreamReader(memoryStream); 

       return reader.ReadToEnd(); 
      } 
     } 

     //deserialize into itself 
     public void Deserialize(string xmlString) 
     { 
      String XmlizedString = null; 

      using (MemoryStream memoryStream = new MemoryStream()) 
      { 
       using (StreamWriter w = new StreamWriter(memoryStream)) 
       { 
        w.Write(xmlString); 
        w.Flush(); 

        XmlSerializer xs = new XmlSerializer(typeof(Configuration)); 
        memoryStream.Seek(0, SeekOrigin.Begin); 
        XmlReader reader = XmlReader.Create(memoryStream); 

        Configuration currentConfig = (Configuration)xs.Deserialize(reader); 

        this.Settings = currentConfig.Settings; 
        this.UIComponents = currentConfig.UIComponents; 

        w.Close(); 
       } 
      } 
     } 
     static void Main(string[] args) 
     { 
      Configuration thisConfig = new Configuration(); 
      thisConfig.Settings = new List<string>(){ 
       "config1", "config2" 
      }; 
      thisConfig.UIComponents = new List<string>(){ 
       "comp1", "comp2" 
      }; 
      //serializing the object 
      string serializedString = thisConfig.Serialize(); 


      Configuration myConfig = new Configuration(); 
      //deserialize into myConfig object 
      myConfig.Deserialize(serializedString); 
     } 
    } 


} 
+0

@CSharpAll: Ihre Klasse verliert auch Ressourcen, wenn eine Ausnahme ausgelöst wird: keine Verwendung von Blöcken. –

+0

fehlen mir irgendwelche Using statements? Ich benutze diese: using System; mit System.Collections.Generic; mit System.Linq; mit System.Text; mit System.Xml; mit System.Runtime.Serialization; mithilfe von System.Xml.Serialization; mit System.IO; – yeahumok

+0

Welchen Fehler bekommen Sie? – CSharpAtl

0

für XML-Serialisierung, haben Sie mehrere Möglichkeiten:

  • manuell
  • Doing XmlSerializer wie oben
  • detaillierte
  • System.Xml verwenden.Serialisierung
  • Linq Mit

für die letzten zwei bis XML, ein Codebeispiel in this Antwort sehen. (Sehen Sie einige Gotchas here)

Und für Ihre rekursive Verzeichnis Besucher könnten Sie darüber nachdenken, es wirklich rekursiv zu machen: here's einige interessante Codebeispiele.

1

John:

Darf ich eine Verbesserung vorschlagen? Verwenden Sie anstelle von Dateinamen die FileInfo object. Dadurch können Sie viel genauere Informationen über jede Datei erhalten, als nur, wenn sie unter demselben Namen existieren.

Auch die XmlSerializer-Klasse sollte Ihnen gut tun. Es wird serialisiert nicht generische Listen, so dass Sie die Ausgabe Ihrer Liste <> auf ein Array haben oder so, aber anders als das:

XmlSerializer serial = new XmlSerializer(typeof(FileInfo[])); 
StringWriter writer = new StringWriter(); 
FileInfo[] fileInfoArray = GetFileInfos(); 
serial.Serialize(writer, fileInfoArrays); 

Einfach und leicht, es sei denn, es ist für Sie wichtig, wie die serialisierten XML sieht aus.

Was auch immer Sie tun, verlieren Sie den leeren Catch-Block. Sie werden es bereuen, Ausnahmen geschluckt zu haben. Loggen Sie sie ein oder werfen Sie sie erneut.

3

Für alle, die Probleme mit XML-Serialisierung und Deserialisierung wird müssen. Ich habe eine Beispielklasse erstellt, um dies zu tun. Es funktioniert auch für rekursive Sammlungen (wie Dateien und Verzeichnisse).

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Sample 
{ 
     [Serializable()] 
     [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "rootnode")] 
     public partial class RootNode 
     { 

      [System.Xml.Serialization.XmlElementAttribute("collection1")] 
      public List<OuterCollection> OuterCollections { get; set; } 
     } 

     [Serializable()] 
     public partial class OuterCollection 
     { 

      [XmlAttribute("attribute1")] 
      public string attribute1 { get; set; } 

      [XmlArray(ElementName = "innercollection1")] 
      [XmlArrayItem("text", Type = typeof(InnerCollection1))] 
      public List<InnerCollection1> innerCollection1Stuff { get; set; } 

      [XmlArray("innercollection2")] 
      [XmlArrayItem("text", typeof(InnerCollection2))] 
      public List<InnerCollection2> innerConnection2Stuff { get; set; } 
     } 

     [Serializable()] 
     public partial class InnerCollection2 
     { 

      [XmlText()] 
      public string text { get; set; } 
     } 

     public partial class InnerCollection1 
     { 

      [XmlText()] 
      public int number { get; set; } 
     } 
} 
+1

-1: Sie sagen, Sie haben diese Klasse erstellt "um dies zu tun", aber ich sehe nicht, dass sie nichts tun. –

+0

Wie er sagte, ist es eine "Probe" -Klasse. Es hat alle gebräuchlichen Elemente, Sie müssen nichts tun, aber Sie müssen es deklarieren. Ganz nett danke – TFD

Verwandte Themen