none
Сериализация класса RRS feed

  • Вопрос

  • Добрый день. Есть такой класс - 

    Option Strict On
    
    <Serializable>
    Public Class ParametersClass
        Inherits Concurrent.ConcurrentDictionary(Of String, DataDescr)
        
        Public Structure DataDescr
            Public Value As Integer
            Public DateChanged As Double
        End Structure
    End Class

    Переменная с набором данных называется Parameters. Сериализация выполнена следующим образом - 

    Dim binFormat As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
    Using fStream As Stream = New FileStream(PathOfTempFiles & "Parameters.dat", FileMode.Create, FileAccess.Write, FileShare.None)
              binFormat.Serialize(fStream, Parameters)
    End Using

    Десериализация - 

    If FileIO.FileSystem.FileExists(PathOfTempFiles & "Parameters.dat") Then
        'Пробуем получить данные
        Using fStream As IO.Stream = IO.File.OpenRead(PathOfTempFiles & "Parameters.dat")
            Parameters = DirectCast(New BinaryFormatter().Deserialize(fStream), ParametersClass)
        End Using            
    End If

    На строке десериализации выбивает "Конец потока обнаружен до завершения разбора". Что не так? :)

    Спасибо.

    19 апреля 2021 г. 16:29

Ответы

  • Стандартный XmlSerializer все это уже реализует. Только что проверил, можно и добавлять и удалять свойства, все обрабатывается отлично. Лишние свойства игнорируются, а недостающие устанавливаются в null/default. Версия сборки вообще нигде не сохраняется. Используйте XML, намного лучшее решение, чем бинарная сериализация. Только от  ConcurrentDictionary придется избавиться, XmlSerializer его не переваривает - нужно преобразовать в массив или список.
    • Помечено в качестве ответа Siompc 20 апреля 2021 г. 15:56
    20 апреля 2021 г. 8:00

Все ответы

  • Обычно такое бывает когда файл при записи не был правильно закрыт и/или буфер записи не был сброшен.

    Попробуйте добавить:

    fStream.Flush()

    fStream.Close()

    Так же помните что двоичный сериалайзер имеет проблемы с безопастностью.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    19 апреля 2021 г. 17:15
    Модератор
  • А какой лучше использовать?

    Который из них будет быстрее работать?

    19 апреля 2021 г. 20:06
  • Не помогло. Ошибка та же. Вставил строки после сериализации
    19 апреля 2021 г. 20:18
  • А какой лучше использовать?

    Который из них будет быстрее работать?

    Оба, они делают разные вещи. 



    This posting is provided "AS IS" with no warranties, and confers no rights.

    19 апреля 2021 г. 20:19
    Модератор
  • Я имел ввиду сериализатор какой лучше)) Я уже прочитал про угрозы. Думаю для такого приложения это не страшно будет. Да и бинарный быстрее остальных. Только вот почему не работает )
    19 апреля 2021 г. 20:26
  • fStream.Position = 0 тоже не помогает
    19 апреля 2021 г. 20:50
  • Еще момент. Я увидел в файле наличие версии программы. Если я в дальнейшем изменю версию, а класс останется такой-же - десериализировать данные предыдущей версии уже не выйдет? 
    19 апреля 2021 г. 20:53
  • fStream.Position = 0 тоже не помогает

    Проверьте работает ли стандартный пример:

    https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.binary.binaryformatter?view=net-5.0



    This posting is provided "AS IS" with no warranties, and confers no rights.

    19 апреля 2021 г. 21:52
    Модератор
  • Еще момент. Я увидел в файле наличие версии программы. Если я в дальнейшем изменю версию, а класс останется такой-же - десериализировать данные предыдущей версии уже не выйдет? 

    Если изменить версию сборки (Assembly version) то я так думаю перестанет работать, а если версию файла (Assembly file version) то нет. Но да, у этого сериалайзера есть проблемы с версиями. Они есть у всех сериалайзеров в общем то.

    Какой сериалайзер использовать зависит от многих факторов. Типично выбор между JSON и XML. JSON быстрее и компактнее, но имеет сложности с поддержкой сложных данных (например со ссылками).

    Если речь идет о значительных объемах данных, то надо думать о базе данных, а не сериалайзерах. А для небольших объемах скорость типично не проблема.



    This posting is provided "AS IS" with no warranties, and confers no rights.

    19 апреля 2021 г. 22:00
    Модератор
  • Уууу.... Не годится тогда. Нужно что бы независимо от версий программа пыталась восстановить данные. И если не получается - создавать их заново. Придется наверное что-то думать в виде простого перебора в цикле всех записей и внесения в текстовый документ.
    19 апреля 2021 г. 22:27
  • Код попробую завтра. Отпишусь
    19 апреля 2021 г. 22:27
  • Уууу.... Не годится тогда. Нужно что бы независимо от версий программа пыталась восстановить данные. И если не получается - создавать их заново. Придется наверное что-то думать в виде простого перебора в цикле всех записей и внесения в текстовый документ.

    Само по себе так работать не будет, требуется поддержка версий в программе. Текстовый документ проблему не решит.

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

    В простом случае можно следовать правилам которые позволят сохранять совместимость, как то:

    - Ничего не убирать.

    - Только добавлять.

    - Все добавленное не обязательно и устанавливается по умолчанию если нет в записи.

    Иначе используется набор специальных мер как то апгрейдеры/конвертеры которые знают как из версии X сделать версию Y. Иногда требуется и обратное преобразование.

    В общем поддержка версий это совсем не простая задача. 


    This posting is provided "AS IS" with no warranties, and confers no rights.

    20 апреля 2021 г. 0:19
    Модератор
  • Стандартный XmlSerializer все это уже реализует. Только что проверил, можно и добавлять и удалять свойства, все обрабатывается отлично. Лишние свойства игнорируются, а недостающие устанавливаются в null/default. Версия сборки вообще нигде не сохраняется. Используйте XML, намного лучшее решение, чем бинарная сериализация. Только от  ConcurrentDictionary придется избавиться, XmlSerializer его не переваривает - нужно преобразовать в массив или список.
    • Помечено в качестве ответа Siompc 20 апреля 2021 г. 15:56
    20 апреля 2021 г. 8:00
  • Стандартный XmlSerializer все это уже реализует. Только что проверил, можно и добавлять и удалять свойства, все обрабатывается отлично. Лишние свойства игнорируются, а недостающие устанавливаются в null/default. Версия сборки вообще нигде не сохраняется. Используйте XML, намного лучшее решение, чем бинарная сериализация. Только от  ConcurrentDictionary придется избавиться, XmlSerializer его не переваривает - нужно преобразовать в массив или список.

    Простейшую поддержку версий JSON/XML поддерживают. 

    А вот более сложные варианты - нет. Например, если переименовать свойство из Foo в Bar, то данные Foo из старой версии в новую Bar перенесены не будут, а просто пропадут. 


    This posting is provided "AS IS" with no warranties, and confers no rights.

    20 апреля 2021 г. 22:53
    Модератор