Serialize/Deserialize class 包含字节数组 属性 到 XML
Serialize/Deserialize class containing byte array property into XML
我的数据 class 将被序列化为 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; }
}
这是我的序列化实用程序 class
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: There is an error in XML document.
hexadecimal value 0x00, is an invalid character.
Upon investigation,我发现某些字符代码对 XML 文档无效。删除无效字符不是一种选择,因为它们构成文件的字节。
我的问题是如何在不去除无效字节的情况下将上述 serialize/deserialize 数据 class 转换为 XML?如果这不可能,有哪些可行的替代方案?
编辑:根据要求,这里是错误的完整堆栈跟踪
System.InvalidOperationException: There is an error in XML document
(1, 21933). ---> System.Xml.XmlException: '.', hexadecimal value 0x00,
is an invalid character. Line 1, position 21933. at
System.Xml.XmlTextReaderImpl.Throw(Exception e) at
System.Xml.XmlTextReaderImpl.Throw(String res, String[] args) at
System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos,
Int32& outOrChars) at System.Xml.XmlTextReaderImpl.ParseText()
at System.Xml.XmlTextReaderImpl.ParseElementContent() at
System.Xml.XmlTextReaderImpl.Read() at
System.Xml.XmlTextReader.Read() at
System.Xml.XmlReader.ReadElementString() at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read2_SPCCommandProtocol(Boolean
isNullable, Boolean checkType) at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read3_SPCCommand()
--- End of inner exception stack trace --- at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader) at
NextSPCFileUpdater.Utilities.XmlSerializer.DeserializeFromString[T](String
xmlString) in C:\Source
Codes\SPC\nextspc-fileupdater\NextSPCFileUpdater\Utilities\XmlSerializer.cs:line
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;
}
如您所见,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);
}
我的数据 class 将被序列化为 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; }
}
这是我的序列化实用程序 class
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: There is an error in XML document. hexadecimal value 0x00, is an invalid character.
Upon investigation,我发现某些字符代码对 XML 文档无效。删除无效字符不是一种选择,因为它们构成文件的字节。
我的问题是如何在不去除无效字节的情况下将上述 serialize/deserialize 数据 class 转换为 XML?如果这不可能,有哪些可行的替代方案?
编辑:根据要求,这里是错误的完整堆栈跟踪
System.InvalidOperationException: There is an error in XML document (1, 21933). ---> System.Xml.XmlException: '.', hexadecimal value 0x00, is an invalid character. Line 1, position 21933. at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args) at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars) at System.Xml.XmlTextReaderImpl.ParseText()
at System.Xml.XmlTextReaderImpl.ParseElementContent() at System.Xml.XmlTextReaderImpl.Read() at System.Xml.XmlTextReader.Read() at System.Xml.XmlReader.ReadElementString() at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read2_SPCCommandProtocol(Boolean isNullable, Boolean checkType) at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read3_SPCCommand() --- End of inner exception stack trace --- at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader) at NextSPCFileUpdater.Utilities.XmlSerializer.DeserializeFromString[T](String xmlString) in C:\Source Codes\SPC\nextspc-fileupdater\NextSPCFileUpdater\Utilities\XmlSerializer.cs:line 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;
}
如您所见,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);
}