XmlException:未显示Document元素 - 第1行,第1行

时间:2013-12-19 18:28:09

标签: c# xml deserialization xml-deserialization

我想要反序列化一个xml字符串,但由于某些原因我收到了标题中声明的错误。

这是我正在反序列化的代码:

public void recieveObject<T>(ref T t){
        XmlSerializer xs = new XmlSerializer(typeof(T));
        Debug.Log("Waiting for client");
        byte[] recievedData = udpc.Receive(ref recieveFromEndPoint);

        if(recievedData.Length > 0){
            string xmlStr = System.Text.Encoding.UTF8.GetString(recievedData, 0, recievedData.Length);
            //xmlStr = xmlStr.Replace("\r","").Replace("\n", "").Replace("\t","").Replace(" ", "");
            Debug.Log(xmlStr);

            MemoryStream rms = new MemoryStream(1024);
            rms.Write (System.Text.Encoding.UTF8.GetBytes(xmlStr), 0, System.Text.Encoding.UTF8.GetBytes(xmlStr).Length);
            Debug.Log ("ms: " + System.Text.Encoding.UTF8.GetString(rms.ToArray()));
            t = (T) xs.Deserialize(rms);
        }
    }

正如你从注释行中看到的那样,我甚至试图剥离出白色空间,但这并没有起作用。

这是我的代码中对recieveObject函数的调用:

recieveObject<Player>(ref player);

这是我的Player类:

using UnityEngine;
using System.Collections;
using System.Xml.Serialization;

[XmlRoot("player")]
public class Player{
    [XmlElement("x")]
    public int x;

    [XmlElement("y")]
    public int y;

    [XmlElement("name")]
    public string name;

    private int maxNameLength = 12;

    public Player(){}
    public Player(int x, int y, string name){
        this.x = x;
        this.y = y;
        if(name.Length > maxNameLength) name = name.Substring(0, maxNameLength);
        this.name = name;
    }
}

最后我尝试使用Xml反序列化为一个播放器对象:

<player>
  <x>50</x>
  <y>100</y>
  <name>Tester</name>
</player>

有人可以告诉我为什么我会在标题中收到错误吗?

感谢您的时间。

1 个答案:

答案 0 :(得分:4)

您正在从内存流末尾读取:

MemoryStream rms = new MemoryStream(1024);
rms.Write (...);

// Now cursor is at end of file, nothing to read here
t = (T) xs.Deserialize(rms);

在反序列化之前,只需将光标移回开头:

rms.Seek(0, SeekOrigin.Begin);
t = (T) xs.Deserialize(rms); // Now deserializer has data to read

最后只是两个小建议。不要忘记丢弃所有一次性物品:

MemoryStream rms = new MemoryStream(1024);
{
}

此外,您不需要将一个字节的流读入字符串(解码UTF8)然后再获取字节(来自UTF8),这种双重转换不会增加任何内容(此外请注意您编码两次,因为您调用{{1}两次):

GetBytes()

出于记录目的,您可以编写这样的函数(UTF8转换仅在必要时完成):

if (recievedData.Length > 0) 
{
    using (MemoryStream rms = new MemoryStream(receivedData))
    {
       t = (T) xs.Deserialize(rms);
    }
}

您的日志记录将是(并且只有在定义了static class Logger { [Conditional("DEBUG")] public static void Debug(Func<string> text) { Debug.Log(text()); } } 符号时才会被调用):

DEBUG

这只是一个更漂亮的替代品:

Logger.Debug(() => "ms: " + Encoding.UTF8.GetString(rms.ToArray()));