将包含字节数组属性的类序列化/反序列化为XML

时间:2015-06-16 02:47:33

标签: c# .net xml serialization .net-4.0

我将序列化为XML的数据类如下所示:

[XmlType(TypeName = "SPCFileInfo")]
[Serializable]
public class SPCFileInfoProtocol
{
    [XmlElement("CompanyCode")]
    public string CompanyCode { get; set; }
    [XmlElement("FileName")]
    public string FileName { get; set; }
    [XmlElement("FileVer")]
    public int FileVer { get; set; }
    [XmlElement("FileSize")]
    public long FileSize { get; set; }
    [XmlElement("CreatedOn")]
    public DateTime CreatedOn { get; set; }
    [XmlElement("LastUpdatedOn")]
    public DateTime LastUpdatedOn { get; set; }
    [XmlElement("FileBytes")]
    public byte[] FileBytes { get; set; }
}

这是我的序列化实用类

public static class XmlSerializer
{
    public static string SerializeToString<T>(T item)
    {
        if (item == null)
        {
            return null;
        }

        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));

        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
        settings.Indent = false;
        settings.OmitXmlDeclaration = false;

        using (StringWriter textWriter = new StringWriter())
        {
            using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                serializer.Serialize(xmlWriter, item);
            }
            return textWriter.ToString();
        }
    }

    public static T DeserializeFromString<T>(string xmlString)
    {
        T item = default(T);

        try
        {
            using (StringReader stringReader = new StringReader(xmlString))
            {
                System.Xml.Serialization.XmlSerializer xmlSerializer =
                new System.Xml.Serialization.XmlSerializer(typeof(T));
                item = (T)xmlSerializer.Deserialize(stringReader);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(ex.ToString());
        }

        return item;
    }
}

序列化为XML工作正常,但是当我尝试反序列化时,我得到以下异常:

  

XMLException:XML文档中存在错误。   十六进制值0x00,是无效字符。

Upon investigation,我发现某些字符代码对XML文档无效。删除无效字符不是一种选择,因为它们构成了文件的字节。

我的问题是如何在不剥离无效字节的情况下将上述数据类序列化/反序列化为XML?如果不可能,有哪些可行的替代方案?

编辑:根据请求,这是错误的完整堆栈跟踪

  

System.InvalidOperationException:XML文档中存在错误   (1,21933)。 ---&GT; System.Xml.XmlException:'。',十六进制值0x00,   是一个无效的字符。第1行,第21933位   System.Xml.XmlTextReaderImpl.Throw(Exception e)at   System.Xml.XmlTextReaderImpl.Throw(String res,String [] args)at   System.Xml.XmlTextReaderImpl.ParseText(Int32&amp; startPos,Int32&amp; endPos,   INT32和放大器; outOrChars)在System.Xml.XmlTextReaderImpl.ParseText()
  在System.Xml.XmlTextReaderImpl.ParseElementContent()中   System.Xml.XmlTextReaderImpl.Read()at   System.Xml.XmlTextReader.Read()at   System.Xml.XmlReader.ReadElementString()at   Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read2_SPCCommandProtocol(布尔   isNullable,Boolean checkType)at   Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read3_SPCCommand()   ---内部异常堆栈跟踪结束---在System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader)   xmlReader,String encodingStyle,XmlDeserializationEvents事件)
  在System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader   xmlReader)at   NextSPCFileUpdater.Utilities.XmlSerializer.DeserializeFromString [T](字符串   C:\ Source中的xmlString)   代码\ SPC \ nextspc-fileupdater \ NextSPCFileUpdater \公用\ XmlSerializer.cs:行   48

这是新版本的反序列化

public static T DeserializeFromString<T>(string xmlString)
{
    T item = default(T);

    try
    {
        using (StringReader stringReader = new StringReader(xmlString))
        using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
        {
            System.Xml.Serialization.XmlSerializer xmlSerializer =
            new System.Xml.Serialization.XmlSerializer(typeof(T));
            item = (T)xmlSerializer.Deserialize(xmlTextReader);
        }
    }
    catch (Exception ex)
    {
        Trace.WriteLine(ex.ToString());
    }

    return item;
}

1 个答案:

答案 0 :(得分:1)

正如您所注意到的,XML文档中可能没有很多字符。但是,这些可以使用正确的转义序列包含在您的数据中。

XmlTextReader的默认设置导致它错误处理 - 我认为它过早地解释了转义序列,但我并不确定。如果我没记错的话,XmlSerializer将创建一个XmlTextReader来包装你传递它的TextReader。要覆盖它,您需要自己创建一个,将XmlTextReader的Normalization属性设置为false

无论我对问题原因的回忆是否正确,将Normalization设置为false都可以解决您的问题:

var xmlReader = new XmlTextReader(textReader) { Normalization = false };

或者更确切地说,在你的情况下:

using (StringReader stringReader = new StringReader(xmlString))
using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
    System.Xml.Serialization.XmlSerializer xmlSerializer =
    new System.Xml.Serialization.XmlSerializer(typeof(T));
    item = (T)xmlSerializer.Deserialize(xmlTextReader);
}

顺便说一句,如果你使用一些using指令,大多数会发现你的代码更具可读性:

using System.Xml;
using System.Xml.Serialization;

using (StringReader stringReader = new StringReader(xmlString))
using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
    item = (T)xmlSerializer.Deserialize(xmlTextReader);
}

如果你使用var,我会发现它更具可读性(虽然我至少有一位不同意的同事):

using System.Xml;
using System.Xml.Serialization;

using (var stringReader = new StringReader(xmlString))
using (var xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
    var xmlSerializer = new XmlSerializer(typeof(T));
    item = (T)xmlSerializer.Deserialize(xmlTextReader);
}