如何在C#中使用XmlSerializer将字节数组序列化为XML?
假设我们有一个结构,它的数据由使用Marshal.PtrToStructure的非托管字节数组提供。
C#结构布局:
[StructLayout(LayoutKind.Sequential, Size = 128, CharSet = CharSet.Ansi, Pack = 1)] public struct MNG_Y_Params { public byte Number; public byte Version; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] OliNumber; public byte InterfaceType; }
字节数组表示非托管代码中的(ascii)字符串。
此结构是另一个结构的成员(具有一些其他成员):
public struct MyData { public int ID; public StructType structType; [XmlElement(ElementName="MNG_Y_Params")] public MNG_Y_Params y_params; [XmlElement(ElementName = "SimpleStruct2")] public SimpleStruct2 ss2; };
所以我们也有这个支持代码
public class XMLIgnore { static public XmlSerializer customserialiser(MyData d) { XmlAttributes attrs = new XmlAttributes(); attrs.XmlIgnore = true; XmlAttributeOverrides xmlOveride = new XmlAttributeOverrides(); switch (d.structType) { case StructType.ST_1: xmlOveride.Add(typeof(MyData), "ss2", attrs); break; case StructType.ST_2: xmlOveride.Add(typeof(MyData), "y_params", attrs); break; default: break; } return new XmlSerializer(typeof(MyData), xmlOveride); } }
和保存方法
static void SaveToXml(object obj, string fileName, XmlSerializer writer) { //XmlSerializer writer = new XmlSerializer(obj.GetType()); using (StreamWriter file = new StreamWriter(fileName)) { writer.Serialize(file, obj); } }
对于示例,我们只生成一些数据。
MNG_Y_Params yParams = new MNG_Y_Params(); yParams.Version = 1; yParams.InterfaceType = 15; yParams.Number = 35; ASCIIEncoding enc = new ASCIIEncoding(); yParams.OliNumber = enc.GetBytes("#1"); MyData md1 = new MyData(); md1.ID = 1; md1.structType = StructType.ST_1; md1.y_params = yParams; XmlSerializer writer = XMLIgnore.customserialiser(md1); SaveToXml(md1, @"C:\temp\dataOne.xml", writer);
预期的XML:
1 ST_1 35 1 #1 15
结果XML:
1 ST_1 35 1 IzE= 15
请关注字节数组成员(OliNumber)结果。
我们可以在这里使用一个属性吗? 我错过了什么?
感谢您的时间和帮助。
宜兰
供参考
默认情况下, XmlSerializer
将使用base 64编码对字节数组进行编码。 如果您使用此站点并粘贴在IzE=
,并对其进行解码,则结果为#1
。 您可以通过设置XmlElementAttribute.DataType来更改编码。 我不确定[XmlElement(DataType = "string")]
是否有效,但您可以尝试一下。 使用[XmlElement(DataType = "hexBinary")]
将生成原始字节。
我使用以下方法使用它:
public class MySerializableClass { [XmlIgnore] public string NaughtyXmlCharactersAsString { get; set; } [XmlElement(ElementName = "NaughtyXmlCharacters", DataType = "hexBinary")] public byte[] NaughtyXmlCharactersAsBytes { get { return Encoding.UTF8.GetBytes(NaughtyCharactersAsString ?? string.Empty); } set { NaughtyXmlCharactersAsString = Encoding.UTF8.GetString(value); } }
然后我只会访问该属性的“AsString”版本。
这就是我做的方式:
public class MySerializableClass { private string dummy; [XmlElement("NaughtyXmlCharacters")] public string NaughtyXmlCharactersAsString { get { return BitConverter.ToString(NaughtyXmlCharacters); } set { // without this, the property is not serialized. dummy = value; } } [XmlIgnore] public byte[] NaughtyXmlCharacters { get; set; } }
然后将字节格式化为hex值,并用减号分隔:00-AF-B1