2009-06-04 3 views
1

У меня есть следующий код:сериализации и десериализации в файл XML, 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; 
     } 
    } 
} 
} 

Код выше работает хорошо рекурсивно найти то, что файлы/каталоги находятся в папке на моем c :.
Я пытаюсь сериализовать результаты того, что этот код делает с XML-файлом, но я не уверен, как это сделать.

Мой проект: найти все файлы/каталоги с диском, сериализовать в файл XML. Затем, во второй раз, когда я запустил это приложение, у меня будет два файла XML для сравнения. Затем я хочу десериализовать XML-файл с первого раза, когда я запускаю это приложение и сравниваю различия с текущим XML-файлом и создаю отчет об изменениях (т. Е. Файлы, которые были добавлены, удалены, обновлены).

Я надеялся получить некоторую помощь, поскольку я новичок в C#, и я очень шаткий по сериализации и десериализации. У меня много проблем с кодированием. Кто-нибудь может мне помочь?

Thanks

ответ

3

Ваш результат: List<string>, и это не является непосредственно сериализуемым. Вы должны обернуть его, минимальный подход:

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

, а затем (De) Сериализация идет как:

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

Но обратите внимание, что вы не будете сравнения XML каким-либо образом (не практично). Вы будете сравнивать (deserialzed) экземпляры списка. И XML отформатирован в формате SOAP, взгляните на него. Это может быть не очень полезно в другом контексте.

И поэтому вы можете легко использовать другой Formatter (двоичный бит является более эффективным и гибким).

Или, может быть, вы просто хотите, чтобы persist Список файлов в формате XML. Это другой вопрос.

0

Помощь # 1. Код отступа на четыре пробела, чтобы его можно было рассматривать как код, когда вы публикуете здесь.

2: избавиться от этого блока try/catch, так как он будет есть все исключения, в том числе те, о которых вы хотите знать.

3: Вы предприняли какие-либо попытки для сериализации результатов? Измените свой вопрос, чтобы показать, что вы пробовали. Подсказка: используйте класс XmlSerializer.

+0

хорошо, я не понимаю, как точно реализовать класс XMLSerializer. я занимаюсь C# в течение 3 месяцев ... и у меня бушуют пробелы в моих знаниях. я сделал примеры, которые я нашел в Интернете, но я понятия не имею, как я буду использовать этот пример, чтобы помочь мне здесь ... и куда поместить любой из самого кода. – yeahumok

+0

@yeahumok: Возможно, вам стоит подумать над тем, является ли «поиск примеров» правильным путем для вас. Некоторые люди хорошо учатся в этой неструктурированной манере. Другие требуют того, кто уже знает структуру знания, чтобы представить его в рациональном порядке. Возможно, это то, что вам нужно. Возможно, что-то вроде http://msdn.microsoft.com/en-us/library/90c86ass(VS.85).aspx поможет вам, а не случайным примерам, которые вы обнаружите. –

1

Этот класс сериализует и десериализует себя .... надеюсь, это поможет.

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: ваш класс также утечки ресурсов, если выбрано исключение: без использования блоков. –

+0

Мне не хватает каких-либо инструкций? Я использую их: using System; с использованием System.Collections.Generic; с использованием System.Linq; с использованием System.Text; с использованием System.Xml; с использованием System.Runtime.Serialization; с использованием System.Xml.Serialization; с использованием System.IO; – yeahumok

+0

какая ошибка вы получаете? – CSharpAtl

0

для XML-сериализации, у вас есть несколько возможностей:

  • Делать это вручную
  • Использование XmlSerializer, как описано выше
  • Использование System.Xml.Сериализация
  • Использование Linq для Xml

для двух последних, см пример кода в this ответ. (См. Некоторые gotchas here)

И для вашего рекурсивного посетителя каталога вы можете подумать о том, чтобы сделать его действительно рекурсивным: here's некоторые интересные примеры кода.

1

John:

Могу ли я предложить улучшение? Вместо использования имен файлов используйте FileInfo object. Это позволит вам получать гораздо более точную информацию о каждом файле, а не только в том случае, если она существует под тем же именем.

Кроме того, класс XmlSerializer должен делать вас просто отлично. Он не будет сериализовать общие списки, так что вы будете выводить ваш список <> массива или некоторые такие, но кроме этого:

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

Простой и легкий, если это не важно для вас, как сериализованные Внешний вид XML.

Независимо от того, что вы делаете, потеряйте пустой блок catch. Вы будете сожалеть о глотании исключений. Запишите их или повторно бросите их.

0

Этот вопрос точно такой же. У меня также есть ответ, который отвечал будет работать для вас, а также:

How to serialize?

3

Для тех, кто испытывает проблемы с XML-сериализации и де-сериализации. Я создал образец класса, чтобы сделать это ниже. Он также работает для рекурсивных коллекций (например, файлов и каталогов).

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: Вы говорите, что создали этот класс «для этого», но я не вижу, чтобы они ничего не делали. –

+0

Как он сказал, это «образец». В нем есть все используемые элементы, вам ничего не нужно делать, но вам нужно объявить об этом. Очень приятно спасибо – TFD

Смежные вопросы