Список сериализации DataContractSerializer <T>при получении ошибки - PullRequest
7 голосов
/ 10 февраля 2011

В настоящее время я пытаюсь сериализовать список, он сериализует (я думаю, хорошо), но когда он десериализуется,

Извините за объем кода, но я действительно застрял и понятия не имею, почему этопроисходит, я также пытался изменить структуру в класс и без помощи.

СПАСИБО.

я получаю следующую ошибку ОБНОВЛЕНО

    There was an error deserializing the object of type There was an error deserializing the object of type 
`System.Collections.Generic.List`1[[A.B.C.DataValues, A.V, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]. Unexpected end of file. Following elements are not closed: Time, DataValues, ArrayOfDataValues.`

Я сериализирую вот так ОБНОВЛЕНО

     public void SerializeDataValue(List<DataValues> values)
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(List<DataValues>));

                using (MemoryStream stream = new MemoryStream())
                {
                    using (GZipStream compress = new GZipStream(stream, CompressionMode.Compress))
                    {
                        XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter(compress);
                        serializer.WriteObject(w, values);

                    }
                    _serializedData = stream.ToArray();
                }
            }

Я десериализирую вот так ОБНОВЛЕНО

 public List<DataValues> DeserializeDataValue()
{
    if (SerializedData == null || SerializedData.Length == 0)
    {
        return new List<DataValues> ();
    }
    else
    {
        DataContractSerializer serializer = new DataContractSerializer(typeof(List<DataValues>));
        using (MemoryStream stream = new MemoryStream(SerializedData))
        {
            using (GZipStream decompress = new GZipStream(stream, CompressionMode.Decompress))
            {
                XmlDictionaryReader r = XmlDictionaryReader.CreateBinaryReader(decompress, XmlDictionaryReaderQuotas.Max);
                return serializer.ReadObject(r, true) as List<DataValues>;
            }
        }
    }
}

Свойства

private byte[] _serializedData;

[DataMember]
[Browsable(false)]
public byte[] SerializedData
{
    get { return _serializedData; }
    set { _serializedData = value; }
}

Методы помощника

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16 * 1024];
    input.Position = 0;
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

Структура

[DataContract(Name = "DataValues", Namespace = "A.B.C")]
public struct DataValues
{
    [DataMember]
    public DateTime Time { get; set; }
    [DataMember]
    public Single Value { get; set; }

    public DataValues(DateTime dateTime, Single value)
    {
        Time = dateTime;
        Value = value;
   }
} 

Ответы [ 4 ]

5 голосов
/ 10 февраля 2011

Это потому, что вы не сериализуете объект (ы) полностью.Вам нужно закрыть поток (ы) после записи, особенно при использовании gzip.Рекомендуемая практика - использовать using:

public void SerializeDataValue(List<DataValues> values)
{
    DataContractSerializer serializer = new DataContractSerializer(typeof(List<DataValues>));
    using (MemoryStream stream = new MemoryStream())
    {
        using (GZipStream compress = new GZipStream(stream, CompressionMode.Compress))
        {
            XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter(compress);
            serializer.WriteObject(w, values);
        }
        _serializedData = stream.ToArray();
    }
}
2 голосов
/ 18 апреля 2012

Извините, что опоздал на этот вопрос.

Проблема с первоначальным подходом состояла в том, что вы просто не смывали (читай: утилизировали) XmlDictionaryWriter .

Это должно сработать (обратите внимание на второе условие использования):

using (GZipStream compress = new GZipStream(stream, CompressionMode.Compress))
using (XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter(compress))
{
    serializer.WriteObject(w, values);
}

Надеюсь, это кому-нибудь поможет.

1 голос
/ 10 февраля 2011

Я могу получить образец для работы, удалив XmlDictionaryReader и вместо этого непосредственно направив поток ввода / вывода в DataContractSerializer.Это может быть дефект в XmlDictionaryReader для больших сжатых коллекций, но я не уверен.

Надеюсь, это поможет:

public void SerializeDataValue(List<DataValues> values)
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(List<DataValues>));
                    using (MemoryStream stream = new MemoryStream())
                {
                    using (GZipStream compress = new GZipStream(stream, CompressionMode.Compress))
                    {
                        serializer.WriteObject(compress , values);

                    }
                    _serializedData = stream.ToArray();
                }
            }

    public List<DataValues> DeserializeDataValue()
    {
        if (SerializedData == null || SerializedData.Length == 0)
        {
            return new List<DataValues> ();
        }
        else
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(List<DataValues>));
            using (MemoryStream stream = new MemoryStream(SerializedData))
            {
                using (GZipStream decompress = new GZipStream(stream, CompressionMode.Decompress))
                {
                    return serializer.ReadObject(decompress , true) as List<DataValues>;
                }
            }
        }
    }
0 голосов
/ 19 апреля 2012

Я столкнулся с точно такой же проблемой и, наконец, нашел решение: XmlDictionaryWriter должен быть удален / закрыт перед тем, как поток, в который вы пишете, сам будет закрыт.Я обнаружил, что благодаря подробному примеру, найденному на http://www.albahari.com/nutshell/ch15.aspx, который является более полным, чем MSDN.

В вашем примере кода это будет:

            using (XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter(compress))
            {
                serializer.WriteObject(w, values);
            }

Вкл.в моем собственном примере использование XmlDictionaryWriter вместо простого и по умолчанию средство записи Xml дало мне только уменьшение размера файла примерно на 25%, но в 3 раза при чтении объекта.

...