从我的xml(反)序列化程序中得到奇怪的结果

本文关键字:结果 程序 xml 我的 序列化 | 更新日期: 2023-09-27 18:20:25

我创建了一个streamExtension,在这里我可以简单地将流从xml文件序列化并取消序列化到xml文件,代码如下:

/// <summary>
/// Contains the logic for streaming extensions.
/// </summary>
public static class StreamExtensions
{
    /// <summary>
    /// Serialize an object.
    /// </summary>
    /// <typeparam name="T">The type of the object that gets serialized.</typeparam>
    /// <param name="stream">The stream to which the bytes will be written.</param>
    /// <param name="serializableObject">The object that gets serialized.</param>
    public static void SerializeObject<T>(this Stream stream, T serializableObject) where T : IXmlSerializable
    {
        var xmlTextWriter = new XmlTextWriter(stream, Encoding.UTF8);
        xmlTextWriter.Formatting = Formatting.Indented;
        xmlTextWriter.IndentChar = ' ';
        xmlTextWriter.Indentation = 4;
        var serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(xmlTextWriter, serializableObject);
        xmlTextWriter.Close();
        stream.Close();
    }
    /// <summary>
    /// Deserialize a stream and return the object.
    /// </summary>
    /// <typeparam name="T">The type of the object that returns from the deserialization.</typeparam>
    /// <param name="stream">The stream which contains the bytes to deserialize.</param>
    /// <returns>The object recovered.</returns>
    public static T DeserializeObject<T>(this Stream stream)
    {
        var xmlTextReader = new XmlTextReader(stream);
        var serializer = new XmlSerializer(typeof(T));
        var result = (T)serializer.Deserialize(xmlTextReader);
        xmlTextReader.Close();
        stream.Close();
        return result;
    }
}

2个非常简单(如果我可以这么说的话:优雅)的序列化和反序列化方法。

我正在使用这个类作为测试:

/// <summary>
/// A serializable class for testing purposes.
/// </summary>
public class SerializableXmlTest : IXmlSerializable
{
    #region Fields
    private string mTestString = string.Empty;
    #endregion
    #region Properties
    /// <summary>
    /// Gets or sets the configuration for this simulation.
    /// </summary>
    /// <value>The configuration for this simulation.</value>
    public string TestString
    {
        get
        {
            return mTestString;
        }
        set
        {
            mTestString = value;
        }
    }
    #endregion
    #region XML serialization region
    /// <summary>
    /// Write the extra information to an XML stream.
    /// </summary>
    /// <param name="writer">Writer to write to.</param>
    public void WriteXml(XmlWriter writer)
    {
        writer.WriteStartElement(MethodBase.GetCurrentMethod().DeclaringType.Name);
        writer.WriteAttributeString("TestString", this.TestString);
        writer.WriteEndElement();
    }
    /// <summary>
    /// Read the extra information from an XML stream.
    /// </summary>
    /// <param name="reader">Reader to read from.</param>
    public void ReadXml(XmlReader reader)
    {
        if ((reader.MoveToContent() == XmlNodeType.Element) && (reader.Name == MethodBase.GetCurrentMethod().DeclaringType.Name))
        {
            reader.Read();
            this.TestString = reader.GetAttribute("TestString");
        }
        reader.ReadEndElement();
    }
    /// <summary>
    /// This method is reserved when implementing the IXmlSerializable interface.
    /// </summary>
    /// <returns>An XmlSchema that describes the XML representation of the
    /// object that is produced by the WriteXml method and consumed by the
    /// ReadXml method.</returns>
    public XmlSchema GetSchema()
    {
        return null;
    }
    #endregion
}

这是我单元测试中的代码:

/// <summary>
/// Test the stream extension class for normal function.
/// </summary>
[Test]
public void TestStreamExtension()
{
    File.Delete(mFileName);
    var testObject = new SerializableXmlTest();
    testObject.TestString = "Test";
    Stream saveFileStream = new FileStream(mFileName, FileMode.OpenOrCreate);
    saveFileStream.SerializeObject(testObject);
    Stream openFileStream = new FileStream(mFileName, FileMode.OpenOrCreate);
    var testObjectClone = openFileStream.DeserializeObject<SerializableXmlTest>();
    Assert.IsTrue(testObject.TestString.Equals(testObjectClone.TestString));
    }

以及输出的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<SerializableXmlTest>
    <SerializableXmlTest TestString="Test" />
</SerializableXmlTest>

然而,有一些事情我不理解,至少其中一个肯定是错误的(我认为)

第一件事是我希望我的xml文件看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<SerializableXmlTest TestString="Test" />

但如果您需要单独的开始和结束元素,我可以理解。

当试图读取它时,第二个元素是阅读器着陆的第一个元素(如预期)<SerializableXmlTest>。然而,如果我继续执行reader.Read()reader.ReadStartElement(),调试器告诉我它当前正在读取:

{Whitespace, Value="'r'n    "}.

这是从哪里来的?为什么它在读一个换行符?显然,当我使用另一个reader.Read()时,我确实到达了xml文件中的<SerializableXmlTest TestString="Test" />行。

我做错了什么?

p.s。明智的做法是告诉您,我稍微更改了serialize和deserialze方法(它们过去一直在工作),但serialize只使用了xmlTextWriter,而没有使用XmlSerializer。并且Deserialize方法使用了流读取器而不是XmlTextReader。但为了让它们变得一样,我遇到了这个问题,我似乎无法解决。

额外的问题:我甚至应该使用XmlTextReader和writer吗?我还可以把我得到的流作为方法参数传递给序列化程序,不是吗?

从我的xml(反)序列化程序中得到奇怪的结果

一些事情。

1) 串行器的故障

XmlSerializer.Serialize(stream, object)

已经写入了文件和开始元素的编码。这就是为什么你会得到奇怪的输出。将WriteXML方法简化为只打开流,剩下的由序列化程序完成。这将修复您编写的XML文件。

2) 'r'n 的读取

目前有两种方法可以访问.NET 中的XML数据

  • XmlReader ' XmlWriter
  • XmlFile

当您使用XmlReader时,您将能够更深入地访问XML文件。这意味着另一方面,一些自动化会丢失。XmlReader.Read()工作完全正确。首先,他发现了一个<符号。所以现在他知道要读,直到他发现>是一个结束标记。然后你让他再读一遍。现在他读到一个'r'n符号。现在他知道他必须停下来,因为你告诉他只读一个字符,但他没有发现<是一个开始标签。

希望这能帮助