无法让 XML(反)序列化程序工作
Posted
技术标签:
【中文标题】无法让 XML(反)序列化程序工作【英文标题】:Can't get XML (de)serializer to work 【发布时间】:2015-12-21 19:14:26 【问题描述】:我一直在做我自己设定的快速挑战;制作一个通用的 XML(反)序列化器。我在这方面的 I/O 部分遇到了问题。代码如下:
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using UnityEngine;
public static class XML
static readonly Dictionary<string, XmlSerializer> PathSerializers = new Dictionary<string, XmlSerializer>();
public static T DeserializeXML<T>(string xmlPath)
var serializer = GetSerializer<T>(xmlPath);
var xml = File.ReadAllText(GetFullPath(xmlPath));
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
return (T) serializer.Deserialize(stream);
public static void SerializeXML<T>(T obj, string xmlPath, bool append)
using (var text = new StreamWriter(GetFullPath(xmlPath), append, Encoding.ASCII))
GetSerializer<T>(xmlPath).Serialize(text, obj);
private static XmlSerializer GetSerializer<T>(string relativePath)
return PathSerializers.ContainsKey(relativePath) ? PathSerializers[relativePath] : AddSerializer<T>(relativePath);
private static string GetFullPath(string relativePath)
return Path.Combine(Application.dataPath, relativePath);
private static XmlSerializer AddSerializer<T>(string relativePath)
if (File.Exists(GetFullPath(relativePath)))
File.Create(GetFullPath(relativePath));
if (PathSerializers.ContainsKey(relativePath))
Debug.Log("Loaded cached serializer");
return GetSerializer<T>(relativePath);
var serializer = new XmlSerializer(typeof(T));
PathSerializers.Add(relativePath, serializer);
return serializer;
可能是我犯了一些疯狂的菜鸟错误,但我根本看不到。
从另一个脚本调用这些方法,并在我知道设置正确的类上调用。
澄清:
如果我序列化然后反序列化相同的数据,我会收到如下错误:
IOException:路径上的共享冲突 C:\Dev\C#\Projects\XML\Assets\leaderboard.xml System.IO.FileStream..ctor(System.String 路径,FileMode 模式, FileAccess 访问、FileShare 共享、Int32 bufferSize、Boolean 匿名,FileOptions 选项)(在 /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/FileStream.cs:320) System.IO.FileStream..ctor(System.String 路径,FileMode 模式, FileAccess 访问、FileShare 共享、Int32 bufferSize)(包装器 remoting-invoke-with-check) System.IO.FileStream:.ctor (字符串,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int) System.IO.File.Create(System.String 路径,Int32 bufferSize)(在 /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/File.cs:135) System.IO.File.Create(System.String 路径)(在 /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/File.cs:130) XML.AddSerializer[Leaderboard] (System.String relativePath) (在 资产/XMLLoader.cs:43) XML.GetSerializer[Leaderboard] (System.String relativePath) (在 Assets/XMLLoader.cs:31) XML.SerializeXML[Leaderboard] (.Leaderboard obj, System.String xmlPath, Boolean append) (at Assets/XMLLoader.cs:25) XMLTest.Start () (在资产/XMLTest.cs:14)
【问题讨论】:
你到底有什么问题? @Bgl86 我添加了一个说明。 看起来该文件已被另一个应用程序打开。 您可以尝试在 SerializeXML 中添加 text.Close() 以确保应用程序在序列化后关闭文件 @Dbuggy 与 text.Close 添加的错误相同。我已经尝试制作一个虚拟文件,并且错误仍然存在,与此无关。它唯一可以打开的地方是 Unity 编辑器,我真的希望编辑器不要那么愚蠢。 编辑我尝试构建项目,但错误仍然存在。 【参考方案1】:我认为这是一个简单的疏忽。如果文件存在,您正在尝试创建该文件!。把条件反过来就好了:
if (!File.Exists(GetFullPath(relativePath)))
File.Create(GetFullPath(relativePath));
【讨论】:
我现在觉得自己非常愚蠢。我怎么看不到呢?【参考方案2】:为了澄清,这是我用来序列化/反序列化 xml 的。
也许通过修改它会对你有所帮助。
/// <summary>
/// Class containing a load and store method to store a datafile as XML format.
/// </summary>
/// <typeparam name="T">The root object containing the data</typeparam>
public class DataFile<T> where T : new()
/// <summary>
/// Load the XML from Path
/// </summary>
/// <param name="path">Path to a XML file containing the data for object of type T</param>
/// <returns>An object of type T as represented by the XML. Will return default(T) when the </returns>
public static T Load(string path)
if (!File.Exists(path)) return default(T);
var ser = new XmlSerializer(typeof(T));
using (var stream = File.OpenRead(path))
var reader = new XmlTextReader(stream);
if (!ser.CanDeserialize(reader))
return default(T); // return null indicating the file can not be loaded
return (T) ser.Deserialize(reader);
/// <summary>
/// Stores an object of type T as XML into a file
/// </summary>
/// <param name="path">A path to a file which should be written.</param>
/// <param name="data">The object to be written to the given file</param>
public static void Store(string path, T data)
var ser = new XmlSerializer(typeof(T));
using (var stream = File.OpenWrite(path))
// Clear the file and write new contents.
stream.SetLength(0);
ser.Serialize(stream, data);
【讨论】:
这个答案肯定会帮助我重新思考我的程序。我想多了,让他们太臃肿了。以上是关于无法让 XML(反)序列化程序工作的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 c# xmlserializer 反序列化以前序列化的 XML
C# Restful WCF 服务。无法在帖子正文中反序列化 XML