C#XML序列化-前导问号 问题

C#XML序列化-前导问号 问题,c#,xml-serialization,C#,Xml Serialization,通过利用我在网上找到的一些示例,我编写了一些XML序列化方法 Method1:序列化对象并返回:(a)类型,(b)xml字符串 方法2:获取上面的(a)和(b)并返回对象 我注意到方法1中的xml字符串包含一个前导“?”。使用方法2重建对象时,这似乎很好 但是,在应用程序中进行一些测试时,有时我们得到的是领先的“??”。这导致方法2在尝试重建对象时引发异常。 本例中的“Object”只是一个简单的int System.InvalidOperationException未处理 Message=

通过利用我在网上找到的一些示例,我编写了一些XML序列化方法

  • Method1:序列化对象并返回:(a)类型,(b)xml字符串
  • 方法2:获取上面的(a)和(b)并返回对象
我注意到方法1中的xml字符串包含一个前导“?”。使用方法2重建对象时,这似乎很好

但是,在应用程序中进行一些测试时,有时我们得到的是领先的“??”。这导致方法2在尝试重建对象时引发异常。 本例中的“Object”只是一个简单的int

System.InvalidOperationException未处理 Message=“XML文档(1,1)中有错误。” Source=“System.Xml” 堆栈跟踪: 在System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader XmlReader,字符串编码样式,XmlDeserializationEvents) 反序列化(XmlReader XmlReader,字符串编码样式) 位于System.Xml.Serialization.XmlSerializer.Deserialize(流) 在C:\Documents and Settings\…Projects\XMLSerialization\Program.cs:第96行中的XMLSerialization.Program.DeserializeXmlStringToObject(字符串xmlString,字符串objectType) 在C:\Documents and Settings\…Projects\XMLSerialization\Program.cs中的XMLSerialization.Program.Main(字符串[]args)处:第49行 有人能解释一下是什么导致了这一切吗

示例代码 下面是我编写代码时编写的mini tester的示例代码,它作为VS控制台应用程序运行。它将显示XML字符串。您还可以取消对区域的注释,以附加额外的前导“?”来重现异常



using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace XMLSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            // deserialize to string
            #region int
            object inObj = 5;
            #endregion

            #region string
            //object inObj = "Testing123";
            #endregion

            #region list
            //List inObj = new List();
            //inObj.Add("0:25");
            //inObj.Add("1:26");
            #endregion

            string[] stringArray = SerializeObjectToXmlString(inObj);

            #region include leading ???
            //int indexOfBracket = stringArray[0].IndexOf('<');
            //stringArray[0] = "??" + stringArray[0];
            #endregion

            #region strip out leading ???
            //int indexOfBracket = stringArray[0].IndexOf('<');
            //string trimmedString = stringArray[0].Substring(indexOfBracket);
            //stringArray[0] = trimmedString;
            #endregion

            Console.WriteLine("Input");
            Console.WriteLine("-----");
            Console.WriteLine("Object Type: " + stringArray[1]);
            Console.WriteLine();
            Console.WriteLine("XML String: " + Environment.NewLine + stringArray[0]);
            Console.WriteLine(String.Empty);

             // serialize back to object
            object outObj = DeserializeXmlStringToObject(stringArray[0], stringArray[1]);

            Console.WriteLine("Output");
            Console.WriteLine("------");

            #region int
            Console.WriteLine("Object: " + (int)outObj);
            #endregion

            #region string
            //Console.WriteLine("Object: " + (string)outObj);
            #endregion

            #region list
            //string[] tempArray;
            //List list = (List)outObj;

            //foreach (string pair in list)
            //{
            //    tempArray = pair.Split(':');
            //    Console.WriteLine(String.Format("Key:{0} Value:{1}", tempArray[0], tempArray[1]));
            //}
            #endregion

            Console.Read();
        }

        private static string[] SerializeObjectToXmlString(object obj)
        {
            XmlTextWriter writer = new XmlTextWriter(new MemoryStream(), Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj);

            MemoryStream stream = (MemoryStream)writer.BaseStream;
            string xmlString = UTF8ByteArrayToString(stream.ToArray());

            string objectType = obj.GetType().FullName;

            return new string[]{xmlString, objectType};
        }

        private static object DeserializeXmlStringToObject(string xmlString, string objectType)
        {
            MemoryStream stream = new MemoryStream(StringToUTF8ByteArray(xmlString));
            XmlSerializer serializer = new XmlSerializer(Type.GetType(objectType));

            object obj = serializer.Deserialize(stream);

            return obj;
        }

        private static string UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetString(characters);
        }

        private static byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetBytes(pXmlString);
        } 


    }
}



使用制度;
使用System.IO;
使用系统文本;
使用System.Xml;
使用System.Xml.Serialization;
命名空间XMLSerialization
{
班级计划
{
静态void Main(字符串[]参数)
{
//反序列化为字符串
#区域整数
对象inObj=5;
#端区
#区域字符串
//对象inObj=“Testing123”;
#端区
#地区名单
//List inObj=新列表();
//inObj.添加(“0:25”);
//inObj.添加(“1:26”);
#端区
string[]stringArray=SerializeObjectToXmlString(inObj);
#区域包括领先的???

//int indexOfBracket=stringArray[0]。IndexOf(“当我以前遇到这个问题时,它通常与编码有关。我会在序列化对象时尝试指定编码。尝试使用以下代码。另外,是否有任何特定的原因需要返回
字符串[]
array?我已将您的方法更改为使用泛型,因此您不必指定类型

private static string SerializeObjectToXmlString<T>(T obj)
{
    XmlSerializer xmls = new XmlSerializer(typeof(T));
    using (MemoryStream ms = new MemoryStream())
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Encoding = Encoding.UTF8;
        settings.Indent = true;
        settings.IndentChars = "\t";
        settings.NewLineChars = Environment.NewLine;
        settings.ConformanceLevel = ConformanceLevel.Document;

        using (XmlWriter writer = XmlTextWriter.Create(ms, settings))
        {
            xmls.Serialize(writer, obj);
        }

        string xml = Encoding.UTF8.GetString(ms.ToArray());
        return xml;
    }
}

private static T DeserializeXmlStringToObject <T>(string xmlString)
{
    XmlSerializer xmls = new XmlSerializer(typeof(T));

    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
    {
        return (T)xmls.Deserialize(ms);
    }
}
私有静态字符串序列化ObjectToXMLString(T obj)
{
XmlSerializer xmls=新的XmlSerializer(typeof(T));
使用(MemoryStream ms=new MemoryStream())
{
XmlWriterSettings=新的XmlWriterSettings();
settings.Encoding=Encoding.UTF8;
settings.Indent=true;
settings.IndentChars=“\t”;
settings.NewLineChars=Environment.NewLine;
settings.ConformanceLevel=ConformanceLevel.Document;
使用(XmlWriter=XmlTextWriter.Create(ms,设置))
{
Serialize(writer,obj);
}
string xml=Encoding.UTF8.GetString(ms.ToArray());
返回xml;
}
}
私有静态T反序列化XmlStringToObject(字符串xmlString)
{
XmlSerializer xmls=新的XmlSerializer(typeof(T));
使用(MemoryStream ms=new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
{
返回(T)xmls.反序列化(ms);
}
}

如果仍然存在问题,请尝试在代码中看到的任何地方使用
Encoding.ASCII
,除非您有使用UTF8的特定原因。我不确定原因,但我看到UTF8编码在序列化时的某些情况下会导致此问题。

这是BOM符号。您可以将其删除

if (xmlString.Length > 0 && xmlString[0] != '<')
{
    xmlString = xmlString.Substring(1, xmlString.Length - 1);
}
并反序列化

using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
{
    serializer.Serialize(writer, instance);
    result = writer.ToString();
}
object result;
using (StringReader reader = new StringReader(instance))
{
    result = serializer.Deserialize(reader);
}

如果您仅在.Net应用程序内部使用此代码,使用UTF32不会产生问题,因为它是.Net内部所有内容的默认编码

您可以发布您的输入和预期输出吗?感谢您的反馈!我想我在实例化XmlTextWriter时指定了编码,是吗?字符串数组就是这样做的我可以返回xml字符串并控制返回的用于反序列化的类型字符串。感谢您的响应!如果这是BOM表,您知道为什么它有时显示为单个前导“?”,有时显示为三个“?”?吗?我唯一的猜测是,序列化数据是使用其他编码读取的,而不是创建时使用的编码。关于长度,这可能会有所不同,因为BOM符号的长度在不同的Unicode编码之间有所不同。但如果您不与其他系统通信,我仍然建议使用UTF-32。