Serialization and Deserialization into an XML file, C#

半腔热情 提交于 2019-12-21 23:12:21

问题


I have the following code:

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;
        }
    }
}
}

The code above works well for recursively finding what files/directories lie in a folder on my c:.
I am trying to serialize the results of what this code does to an XML file but I am not sure how to do this.

My project is this: find all files/ directories w/in a drive, serialize into an XML file. Then, the second time i run this app, i will have two XML files to compare. I then want to deserialize the XML file from the first time i ran this app and compare differences to the current XML file and produce a report of changes (i.e. files that have been added, deleted, updated).

I was hoping to get some help as I am a beginner in C# and i am very very shaky on serializing and deserializing. I'm having lots of trouble coding. Can someone help me?

Thanks


回答1:


Your result is List<string> and that is not directly serializable. You'll have to wrap it, a minimal approach:

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

And then the (De)Serialization goes like:

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);
}

But note that you will not be comparing the XML in any way (not practical). You will compare (deserialzed) List instances. And the XML is SOAP formatted, take a look at it. It may not be very useful in another context.

And therefore you could easily use a different Formatter (binary is a bit more efficient and flexible).

Or maybe you just want to persist the List of files as XML. That is a different question.




回答2:


For anyone who is having trouble with xml serialization and de-serialization. I have created a sample class to do this below. It works for recursive collections also (like files and directories).

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; }
        }
}



回答3:


This class serializes and deserializes itself....hopefully this helps.

 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);
        }
    }


}



回答4:


John:

May I suggest an improvement? Instead of using filenames, use the FileInfo object. This will allow you to get much more accurate information about each file rather than just if it exists under the same name.

Also, the XmlSerializer class should do you just fine. It won't serialize generic lists, so you'll have to output your List<> to an array or some such, but other than that:

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

Simple and easy, unless it matters to you how the serialized XML looks.

Whatever you do, lose the empty catch block. You WILL regret swallowing exceptions. Log them or re-throw them.




回答5:


Help #1. Indent code by four spaces to have it be seen as code when you post here.

2: get rid of that try/catch block, as it will eat all exceptions, including the ones you want to know about.

3: Did you make any attempt at all to serialize your results? Please edit your question to show what you tried. Hint: use the XmlSerializer class.




回答6:


for xml serialisation, you have several possibilities:

  • Doing it manually
  • Using XmlSerializer as detailed above
  • Using System.Xml.Serialization
  • Using Linq to Xml

for the last two, see a code example in this answer. (See some gotchas here)

And for your recursive directory visitor, you could consider making it really recursive: here's some interesting code examples.




回答7:


This question is exactly like this one. I also have a posted answer which will work for you as well:

How to serialize?



来源:https://stackoverflow.com/questions/952264/serialization-and-deserialization-into-an-xml-file-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!