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

C# 将包含字节数组属性的类序列化/反序列化为XML,c#,.net,xml,serialization,.net-4.0,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;

将序列化为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;
    }
}
公共静态类XmlSerializer
{
公共静态字符串SerializeToString(T项)
{
如果(项==null)
{
返回null;
}
System.Xml.Serialization.XmlSerializer serializer=new System.Xml.Serialization.XmlSerializer(typeof(T));
XmlWriterSettings=新的XmlWriterSettings();
settings.Encoding=newunicodeincoding(false,false);//在.NET字符串中没有BOM
settings.Indent=false;
settings.OmitXmlDeclaration=false;
使用(StringWriter textWriter=new StringWriter())
{
使用(XmlWriter=XmlWriter.Create(textWriter,设置))
{
serializer.Serialize(xmlWriter,item);
}
返回textWriter.ToString();
}
}
公共静态T反序列化FromString(字符串xmlString)
{
T项=默认值(T);
尝试
{
使用(StringReader StringReader=new StringReader(xmlString))
{
System.Xml.Serialization.XmlSerializer XmlSerializer=
新的System.Xml.Serialization.XmlSerializer(typeof(T));
item=(T)xmlSerializer.Deserialize(stringReader);
}
}
捕获(例外情况除外)
{
Trace.WriteLine(例如ToString());
}
退货项目;
}
}
序列化为XML很好,但当我尝试反序列化时,会出现以下异常:

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

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

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

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

System.InvalidOperationException:XML文档中存在错误 (1, 21933). ---> System.Xml.XmlException:“.”,十六进制值0x00, 是无效字符。第1行,位置21933。在 System.Xml.XmlTextReaderImpl.Throw(异常e)位于 System.Xml.XmlTextReaderImpl.Throw(字符串res,字符串[]args)位于 System.Xml.XmlTextReaderImpl.ParseText(Int32和startPos、Int32和endPos、, Int32&outOrChars)位于System.Xml.XmlTextReaderImpl.ParseText()
位于System.Xml.XmlTextReaderImpl.ParseElementContent()处 System.Xml.XmlTextReaderImpl.Read()位于 System.Xml.XmlTextReader.Read()位于 System.Xml.XmlReader.ReadElementString()位于 Microsoft.Xml.Serialization.GenerateAssembly.XmlSerializationReaderSPCCommandProtocol.Read2_SPCCommandProtocol(布尔值 isNullable,Boolean checkType)位于 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read3_SPCCommand() ---内部异常堆栈跟踪结束---位于System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader、字符串编码样式、XmlDeserializationEvents)
在System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader)中 xmlReader)在 NextSPCFileUpdater.Utilities.XmlSerializer.DeserializeFromString[T](字符串 C:\Source中的xmlString) Codes\SPC\nextspc文件更新程序\nextspc文件更新程序\Utilities\XmlSerializer.cs:line 四十八

这是反序列化的新版本

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;
}
public static T反序列化fromstring(string xmlString)
{
T项=默认值(T);
尝试
{
使用(StringReader StringReader=new StringReader(xmlString))
使用(XmlTextReader XmlTextReader=newXMLTEXTREADER(stringReader){Normalization=false})
{
System.Xml.Serialization.XmlSerializer XmlSerializer=
新的System.Xml.Serialization.XmlSerializer(typeof(T));
item=(T)xmlSerializer.Deserialize(xmlTextReader);
}
}
捕获(例外情况除外)
{
Trace.WriteLine(例如ToString());
}
退货项目;
}

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

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

但是,无论我对问题原因的记忆是否正确,将
标准化设置为
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 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
(尽管我至少有一位同事不同意),则会发现它更具可读性:


奇怪。。即使正常化设置为false,我也会收到一个相同的错误。@l46kok您能发布当前代码和异常消息的全文吗,包括内部异常?代码相当长,因为它处理套接字通信,但我会尽力裁剪出相关的异常parts@I只是指您将标准化设置为false所做的更改。异常消息更重要。@l46kok您检查了位置21933处的字符串了吗?它实际上是否包含零字符?我无法重现您的错误,可能是因为我的字节数组与您的不同。
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);
}