序列化和反序列化成 XML 文件,C#
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/952264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serialization and Deserialization into an XML file, C#
提问by yeahumok
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.
上面的代码适用于递归查找我的 c: 上的文件夹中的文件/目录。
我正在尝试将此代码对 XML 文件执行的操作的结果序列化,但我不确定如何执行此操作。
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).
我的项目是这样的:找到驱动器中的所有文件/目录,序列化为一个 XML 文件。然后,第二次运行这个应用程序时,我将有两个 XML 文件进行比较。然后我想从我第一次运行这个应用程序开始反序列化 XML 文件,并比较与当前 XML 文件的差异并生成更改报告(即已添加、删除、更新的文件)。
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?
我希望得到一些帮助,因为我是 C# 的初学者,而且我在序列化和反序列化方面非常不稳定。我在编码时遇到了很多麻烦。有人能帮我吗?
Thanks
谢谢
采纳答案by Henk Holterman
Your result is List<string>
and that is not directly serializable. You'll have to wrap it, a minimal approach:
您的结果是List<string>
并且不能直接序列化。你必须包装它,一种最小的方法:
[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.
但请注意,您不会以任何方式比较 XML(不实用)。您将比较(反序列化) List 实例。而且 XML 是 SOAP 格式的,看看它。在另一种情况下它可能不是很有用。
And therefore you could easily use a different Formatter (binary is a bit more efficient and flexible).
因此,您可以轻松使用不同的格式化程序(二进制更高效和灵活)。
Or maybe you just want to persistthe List of files as XML. That is a different question.
或者,也许你只是想坚持文件作为XML的列表。那是一个不同的问题。
回答by John Saunders
Help #1. Indent code by four spaces to have it be seen as code when you post here.
帮助 #1。将代码缩进四个空格,以便在您在此处发布时将其视为代码。
2: get rid of that try/catch block, as it will eat allexceptions, including the ones you want to know about.
2:摆脱那个 try/catch 块,因为它会吃掉所有的异常,包括你想知道的那些。
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.
3:您是否曾尝试将结果序列化?请编辑您的问题以显示您尝试过的内容。提示:使用 XmlSerializer 类。
回答by CSharpAtl
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);
}
}
}
回答by Benjol
for xml serialisation, you have several possibilities:
对于 xml 序列化,您有几种可能性:
- Doing it manually
- Using XmlSerializer as detailed above
- Using System.Xml.Serialization
- Using Linq to Xml
- 手动操作
- 使用上面详述的 XmlSerializer
- 使用 System.Xml.Serialization
- 使用 Linq 转 Xml
for the last two, see a code example in thisanswer. (See some gotchas here)
对于最后两个,请参阅此答案中的代码示例。(在这里查看一些问题)
And for your recursive directory visitor, you could consider making it really recursive: here'ssome interesting code examples.
对于您的递归目录访问者,您可以考虑使其真正递归:这里有一些有趣的代码示例。
回答by Faqa
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.
我可以建议改进吗?不使用文件名,而是使用FileInfo 对象。这将允许您获得关于每个文件的更准确的信息,而不仅仅是它是否以相同的名称存在。
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 类应该可以很好地满足您的需求。它不会序列化通用列表,因此您必须将 List<> 输出到数组或其他数组,但除此之外:
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.
简单易行,除非序列化 XML 的外观对您很重要。
Whatever you do, lose the empty catch block. You WILL regret swallowing exceptions. Log them or re-throw them.
无论你做什么,都会丢失空的 catch 块。你会后悔吞下异常。记录它们或重新抛出它们。
回答by CodeLikeBeaker
This question is exactly like this one. I also have a posted answer which will work for you as well:
这个问题和这个问题完全一样。我也有一个已发布的答案,它也适用于您:
回答by Tim
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).
对于在 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; }
}
}