Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中使用XmlSerializer将字节数组序列化为XML?_C#_Xml_Serialization_Unmanaged - Fatal编程技术网

如何在C#中使用XmlSerializer将字节数组序列化为XML?

如何在C#中使用XmlSerializer将字节数组序列化为XML?,c#,xml,serialization,unmanaged,C#,Xml,Serialization,Unmanaged,假设我们有一个结构,它的数据是由使用Marshal.PtrToStructure的非托管字节数组提供的 C#struct布局: [StructLayout(LayoutKind.Sequential, Size = 128, CharSet = CharSet.Ansi, Pack = 1)] public struct MNG_Y_Params { public byte Number; public byte Version; [MarshalAs(Unmanaged

假设我们有一个结构,它的数据是由使用Marshal.PtrToStructure的非托管字节数组提供的

C#struct布局:

[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 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:

<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ID>1</ID>
  <structType>ST_1</structType>
  <MNG_Y_Params>
    <Number>35</Number>
    <Version>1</Version>
    <OliNumber>#1</OliNumber>
    <InterfaceType>15</InterfaceType>
  </MNG_Y_Params>
</MyData>

1.
圣卢西亚1号
35
1.
#1
15
结果XML:

<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ID>1</ID>
  <structType>ST_1</structType>
  <MNG_Y_Params>
    <Number>35</Number>
    <Version>1</Version>
    <OliNumber>IzE=</OliNumber>
    <InterfaceType>15</InterfaceType>
  </MNG_Y_Params>
</MyData>

1.
圣卢西亚1号
35
1.
化=
15
请关注字节数组成员(OliNumber)结果

这里有一个我们可以使用的属性吗? 我错过了什么

谢谢你的时间和帮助

宜兰


对于,默认情况下
XmlSerializer
将使用base 64编码对字节数组进行编码。如果使用站点并粘贴到
IzE=
,然后对其进行解码,结果将是
#1
。您可以通过设置来更改编码。我不确定
[xmlement(DataType=“string”)]
是否有效,但您可以试试。使用
[xmlement(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;
    }
}

然后将字节格式化为十六进制值,并用减号分隔:00-AF-B1

反序列化时,OliNumber中的数据是否与序列化之前不同?XML中的值可能很好,可能只是XMLSerializer用于字节数组的格式。@Kipotlov感谢您的评论。反序列化工作正常,但关键是在XML中表示来自非托管代码的数据,其中字节数组表示(ascii)字符串。序列化程序将
byte[]
视为二进制数据而不是字符串,因此它使用传输编码(base64)允许任意二进制数据通过XML。请阅读规范,XML不允许在内容中使用大多数非打印字符。如果您发送的是字符串,请将其称为
string
。我知道这很旧,但我相信如果您更改编码。。。对于utf-16,它可能会起作用。您没有讨论基本字符集,因此可能在XML转换器中遇到了一个问题。我在处理其他语言集的翻译时遇到了这个问题。utf-16拾取了utf-8未拾取的双字节字符。谢谢,尝试了您的建议。在创建自定义的“XmlSerializer”时出现异常:““string”是XmlElementAttribute.DataType属性的无效值。string无法转换为System.byte[]”。至于另一个选项“HexBinary”的结果是:'2331'@IIan-是的,这正是我所期望的。我认为,如果想要字符串值输出,就必须实现IXmlSerializable并自己完成。
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;
    }
}