解压缩数据流组件:未知块类型。流可能已损坏

时间:2016-03-15 22:15:10

标签: c# xml stream deserialization

我正在尝试解压缩/反序列化保存在XML文件属性中的数据流。使用Delphi的Stream.WriteComponent()方法压缩数据。它最终会抛出这个错误:

例外: System.IO.InvalidDataException:未知块类型。流可能已损坏。

首先,我使用XML LINQ查询检索数据流:

var dataStream = 
(
    from XmlNode xn in nList
    where xn?.Attributes != null 
    && xn?.Attributes["Name"].InnerText == "Columns"
    select xn.Attributes["StreamData"].InnerText
).ToList()[0x0];
if (string.IsNullOrEmpty(dataStream) { return; }

然后我继续使用XML属性InnerText并将其转换为流数据:

var byteStream = Encoding.UTF8.GetBytes(dataStream);
var memStream = new MemoryStream
(
    byteStream,
    0,
    byteStream.Length,
    true,
    true
);

然后我继续尝试解压缩数据流:

var rslt = Decompress(stream);

这就是Decompress()函数的样子:

public static string Decompress(MemoryStream stream)
{
    using (var uncompressed = new MemoryStream())
    using (var compressed = stream)
    using (var ds = new DeflatedStream(compressed, CompressionMode.Decompress))
    {
        ds.CopyTo(uncompressed);
        return Encoding.UTF8.GetString(uncompressed.ToArray());
    }
}

XML文件看起来与此类似但不相同(它是有效的xml我承诺):

<?xml version="1.0" encoding="UTF-8"?>
<Item Class="Item" Name="Default" GUID="{BC0EE2E4-641F-44DA-A989-F97C58B1828D}">
  <Properties>
    <Property Class="Type" GUID="{3A6C51FB-BE2E-4DBF-B2C5-8EB7C3508529}" Name="Type" group="Item" OrderIndex="0" DecimalPlaces="2">blah</Property>
    <Property Class="Text" GUID="{1119FF79-74C6-42AF-918F-1AF485614D07}" Name="Name" inheritaction="Ignore" required="True" group="Item" OrderIndex="1" DecimalPlaces="2">blahblah</Property>
    <Property Class="Number" GUID="{AF1BC5FD-A4DD-4610-92EE-2F7D7EA4FA64}" Name="OrderIndex" systemhidden="True" OrderIndex="3" DecimalPlaces="2">0</Property>
    <Property Class="Text" GUID="{176382CA-7E00-47C2-8DD3-82A9ED4FB973}" Name="GUID" inheritaction="Ignore" systemlocked="True" systemhidden="True" OrderIndex="4" DecimalPlaces="2">{BC0EE2E4-641F-44DA-A989-F97C58B1828D}</Property>
    <Property Class="Stream" GUID="{833CB9FD-4914-4899-B757-CC9C130E6914}" Name="Columns" OrderIndex="5" DecimalPlaces="2" StreamData="VFBGMB1UcHNjeEVzdGltYXRpbmdUcmVlTGlzdENvbHVtbgZDb2x1bW4MQ2FwdGlvbi5UZXh0BgROYW1lFURhdGFCaW5kaW5nLlZhbHVlVHlwZQYGU3RyaW5nBVdpZHRoAzgBEVBvc2l0aW9uLkNvbEluZGV4AgARUG9zaXRpb24uUm93SW5kZXgCABJQb3NpdGlvbi5CYW5kSW5kZXgCAAlTaG93VW5pdHMIDUlzVW5pdHNDb2x1bW4IAABUUEYwHVRwc2N4RXN0aW1hdGluZ1RyZWVMaXN0Q29sdW1uB0NvbHVtbjIMQ2FwdGlvbi5UZXh0BgtEZXNjcmlwdGlvbhVEYXRhQmluZGluZy5WYWx1ZVR5cGUGBlN0cmluZwVXaWR0aAJsEVBvc2l0aW9uLkNvbEluZGV4AgERUG9zaXRpb24uUm93SW5kZXgCABJQb3NpdGlvbi5CYW5kSW5kZXgCAAlTaG93VW5pdHMIDUlzVW5pdHNDb2x1bW4IAABUUEYwHVRwc2N4RXN0aW1hdGluZ1RyZWVMaXN0Q29sdW1uD1RyZWVMaXN0Q29sdW1uMhNQcm9wZXJ0aWVzQ2xhc3NOYW1lBhJUY3hMYWJlbFByb3BlcnRpZXMZUHJvcGVydGllcy5BbGlnbm1lbnQuSG9yegcNdGFMZWZ0SnVzdGlmeQxDYXB0aW9uLlRleHQGBUNvbG9yFURhdGFCaW5kaW5nLlZhbHVlVHlwZQYGU3RyaW5nBVdpZHRoAiwRUG9zaXRpb24uQ29sSW5kZXgCCBFQb3NpdGlvbi5Sb3dJbmRleAIAElBvc2l0aW9uLkJhbmRJbmRleAIACVNob3dVbml0cwgNSXNVbml0c0NvbHVtbggAAFRQRjAdVHBzY3hFc3RpbWF0aW5nVHJlZUxpc3RDb2x1bW4OVHJlZUxpc3RDb2x1bW4TUHJvcGVydGllc0NsYXNzTmFtZQYSVGN4TGFiZWxQcm9wZXJ0aWVzGVByb3BlcnRpZXMuQWxpZ25tZW50LkhvcnoHDnRhUmlnaHRKdXN0aWZ5DENhcHRpb24uVGV4dAYDUXR5FURhdGFCaW5kaW5nLlZhbHVlVHlwZQYFRmxvYXQOT3B0aW9ucy5Gb290ZXIJBVdpZHRoAmQRUG9zaXRpb24uQ29sSW5kZXgCAhFQb3NpdGlvbi5Sb3dJbmRleAIAElBvc2l0aW9uLkJhbmRJbmRleAIAElN1bW1hcnlGb290ZXIuS2luZAcFc2tTdW0JU2hvd1VuaXRzCQ1Jc1VuaXRzQ29sdW1uCAAAVFBGMB1UcHNjeEVzdGltYXRpbmdUcmVlTGlzdENvbHVtbg9UcmVlTGlzdENvbHVtbjQTUHJvcGVydGllc0NsYXNzTmFtZQYSVGN4TGFiZWxQcm9wZXJ0aWVzGVByb3BlcnRpZXMuQWxpZ25tZW50LkhvcnoHDnRhUmlnaHRKdXN0aWZ5DENhcHRpb24uVGV4dAYKUHJpY2UgRWFjaBVEYXRhQmluZGluZy5WYWx1ZVR5cGUGBUZsb2F0Dk9wdGlvbnMuRm9vdGVyCQVXaWR0aAJkEVBvc2l0aW9uLkNvbEluZGV4AgYRUG9zaXRpb24uUm93SW5kZXgCABJQb3NpdGlvbi5CYW5kSW5kZXgCABJTdW1tYXJ5Rm9vdGVyLktpbmQHBXNrU3VtCVNob3dVbml0cwgNSXNVbml0c0NvbHVtbggAAFRQRjAdVHBzY3hFc3RpbWF0aW5nVHJlZUxpc3RDb2x1bW4PVHJlZUxpc3RDb2x1bW41E1Byb3BlcnRpZXNDbGFzc05hbWUGElRjeExhYmVsUHJvcGVydGllcxlQcm9wZXJ0aWVzLkFsaWdubWVudC5Ib3J6Bw50YVJpZ2h0SnVzdGlmeQxDYXB0aW9uLlRleHQGC1ByaWNlIFRvdGFsFURhdGFCaW5kaW5nLlZhbHVlVHlwZQYFRmxvYXQOT3B0aW9ucy5Gb290ZXIJBVdpZHRoAmQRUG9zaXRpb24uQ29sSW5kZXgCBxFQb3NpdGlvbi5Sb3dJbmRleAIAElBvc2l0aW9uLkJhbmRJbmRleAIAFFN1bW1hcnlGb290ZXIuRm9ybWF0Bg1bIUNVXSMsIyMwLjAwElN1bW1hcnlGb290ZXIuS2luZAcFc2tTdW0JU2hvd1VuaXRzCA1Jc1VuaXRzQ29sdW1uCAAAVFBGMB1UcHNjeEVzdGltYXRpbmdUcmVlTGlzdENvbHVtbg5HcmlkVW50c0NvbHVtbgxDYXB0aW9uLlRleHQGBVVuaXRzFURhdGFCaW5kaW5nLlZhbHVlVHlwZQYGU3RyaW5nD09wdGlvbnMuRWRpdGluZwgFV2lkdGgCMRFQb3NpdGlvbi5Db2xJbmRleAIDEVBvc2l0aW9uLlJvd0luZGV4AgASUG9zaXRpb24uQmFuZEluZGV4AgAJU2hvd1VuaXRzCA1Jc1VuaXRzQ29sdW1uCQ1Vbml0Rm9yQ29sdW1uBgNRdHkAAFRQRjAdVHBzY3hFc3RpbWF0aW5nVHJlZUxpc3RDb2x1bW4PVHJlZUxpc3RDb2x1bW4zE1Byb3BlcnRpZXNDbGFzc05hbWUGElRjeExhYmVsUHJvcGVydGllcxlQcm9wZXJ0aWVzLkFsaWdubWVudC5Ib3J6Bw50YVJpZ2h0SnVzdGlmeQxDYXB0aW9uLlRleHQGCUNvc3QgRWFjaBVEYXRhQmluZGluZy5WYWx1ZVR5cGUGBUZsb2F0Dk9wdGlvbnMuRm9vdGVyCQVXaWR0aAJkEVBvc2l0aW9uLkNvbEluZGV4AgQRUG9zaXRpb24uUm93SW5kZXgCABJQb3NpdGlvbi5CYW5kSW5kZXgCABRTdW1tYXJ5Rm9vdGVyLkZvcm1hdAYNWyFDVV0jLCMjMC4wMBJTdW1tYXJ5Rm9vdGVyLktpbmQHBXNrU3VtCVNob3dVbml0cwgNSXNVbml0c0NvbHVtbggAAFRQRjAdVHBzY3hFc3RpbWF0aW5nVHJlZUxpc3RDb2x1bW4PVHJlZUxpc3RDb2x1bW42E1Byb3BlcnRpZXNDbGFzc05hbWUGElRjeExhYmVsUHJvcGVydGllcxlQcm9wZXJ0aWVzLkFsaWdubWVudC5Ib3J6Bw50YVJpZ2h0SnVzdGlmeQxDYXB0aW9uLlRleHQGCE1hcmt1cCAlFURhdGFCaW5kaW5nLlZhbHVlVHlwZQYFRmxvYXQOT3B0aW9ucy5Gb290ZXIJBVdpZHRoAkMRUG9zaXRpb24uQ29sSW5kZXgCBRFQb3NpdGlvbi5Sb3dJbmRleAIAElBvc2l0aW9uLkJhbmRJbmRleAIAElN1bW1hcnlGb290ZXIuS2luZAcFc2tTdW0JU2hvd1VuaXRzCA1Jc1VuaXRzQ29sdW1uCAAA"/>

  </Properties>
</Item>

1 个答案:

答案 0 :(得分:1)

由于XML是一个字符串,并且解压缩几乎肯定需要二进制数据作为输入,因此StreamData属性的值必须是二进制数据的ASCII /字符串编码表示。这可能是使用简单的bin-2-hex表示法,但从问题中提供的示例中,它看起来更可能是 base64 或类似。

提供XML的人应该能够为您确认编码。

无论如何,我们可以相当确定StreamData必须采用字符串编码形式,否则二进制数据将包含将导致无效XML文件的值(例如,值为0的字节等) )

在这种情况下,你的问题是Encoding.UTF8.GetBytes()将它传递的数据解释为一个字节数组。也就是说,它期望它给出的字节是有效的UTF8编码字符串的一部分。 执行从十六进制字符到二进制字节等的任何转换。

也就是说,要使用一个非常简单的示例,如果您的StreamData是一个值为"000102"的字符串,那么您的代码目前将产生一个内容由6组成的byteStream(六)字节值如下:

StreamData :  '0' '0' '0' '1' '0' '2'
bytes      : [30][30][30][31][30][32]    (hexadecimal byte values)

当您可能期望的是3(3)个字节的流,其值对应于StreamData,如下所示:

StreamData : '00''01''02'
bytes      : [00][01][02]                (hexadecimal byte values)

即。在将StreamData字符串传递给解压缩()例程之前,你需要将StreamData字符串正确地解码为它的内存二进制表示,因为二进制数据它正在抱怨正在提供的是无效的压缩数据。

您需要在<% if current_user.email.end_with? "@mailinator.com" %> <%= email_field_tag :email, nil, placeholder: 'Enter email...' %> <% else %> Send email to <%= text_field_tag :email, current_user.email %> <% end %> 中确认二进制数据的编码并应用相应的解码来获取该数据的二进制表示,然后再将其传递给解压缩()例程,而不是比原始/原始字符串表示。