serializing data to a file

  • Thread starter Thread starter PJ6
  • Start date Start date
P

PJ6

OK I haven't ever done this before... I'm going to need to create "project"
files to which my application can save and retreive data. Rather than
worrying about the details fo the format too much, I'd like to just have
everything saved as a serialized collection so whatever I chose to store in
a file can be kind of arbitrary. I thought I'd use the .resx model VS uses
for storing forms information, but the resource manager does no allow
writing and anyhow I'm not sure this is the best way to do it. Can anyone
point me to so good examples on how best to approach this?

TIA,
Paul
 
Hi Paul,

This is typically fairly simple to do. You can mark your classes with the
<Serializable ()> attribute. Then just use an XMLSerializer to write to and
load from a file. What version of the framework are you using? If you're
on 2.0, you can use generics to encapsulate this kind of functionality...
Here's a class I created to facilitate this.

Regards,

Michael Bosch

Namespace Utilities

''' <summary>
''' Provides a generic way to create an XML file from
''' any class that is serializable.
''' </summary>
''' <typeparam name="t">The type of class you wish to create an XML file
from.</typeparam>
''' <remarks></remarks>
''' <example>
''' <code>
''' Dim doc As New Utilities.PersistableDocument(Of Customer)
'''
''' With doc
''' .Value.FirstName = "Mike"
''' .Value.LastName = "Bosch"
''' .Save("C:\customer.xml")
''' End With
''' </code>
''' Or alternatively using a predefined value:
''' <code>
''' Dim doc As New Utilities.PersistableDocument(Of Customer)(obj)
''' doc.Save("C:\customer.xml")
''' </code>
''' </example>
'''

<Serializable()> _
Public Class PersistableDocument(Of t As New)

Private mValue As New t

Public Property Value() As t
Get
Return mValue
End Get
Set(ByVal value As t)
mValue = value
End Set
End Property

Public Sub Save(ByVal fileName As String)

Using fs As New IO.FileStream(fileName, IO.FileMode.Create)
Dim xser As New
System.Xml.Serialization.XmlSerializer(GetType(t))
xser.Serialize(fs, mValue)
End Using

End Sub

Public Sub Load(ByVal fileName As String)

Using fs As New IO.FileStream(fileName, IO.FileMode.Open)
Dim xser As New Xml.Serialization.XmlSerializer(GetType(t))
mValue = DirectCast(xser.Deserialize(fs), t)
End Using

End Sub

Public Sub New(ByVal value As t)
Me.mValue = value
End Sub

Public Sub New()

End Sub
End Class

End Namespace
 
Nice!

Thanks :)

Paul

Michael Bosch said:
Hi Paul,

This is typically fairly simple to do. You can mark your classes with the
<Serializable ()> attribute. Then just use an XMLSerializer to write to
and load from a file. What version of the framework are you using? If
you're on 2.0, you can use generics to encapsulate this kind of
functionality... Here's a class I created to facilitate this.

Regards,

Michael Bosch

Namespace Utilities

''' <summary>
''' Provides a generic way to create an XML file from
''' any class that is serializable.
''' </summary>
''' <typeparam name="t">The type of class you wish to create an XML
file from.</typeparam>
''' <remarks></remarks>
''' <example>
''' <code>
''' Dim doc As New Utilities.PersistableDocument(Of Customer)
'''
''' With doc
''' .Value.FirstName = "Mike"
''' .Value.LastName = "Bosch"
''' .Save("C:\customer.xml")
''' End With
''' </code>
''' Or alternatively using a predefined value:
''' <code>
''' Dim doc As New Utilities.PersistableDocument(Of Customer)(obj)
''' doc.Save("C:\customer.xml")
''' </code>
''' </example>
'''

<Serializable()> _
Public Class PersistableDocument(Of t As New)

Private mValue As New t

Public Property Value() As t
Get
Return mValue
End Get
Set(ByVal value As t)
mValue = value
End Set
End Property

Public Sub Save(ByVal fileName As String)

Using fs As New IO.FileStream(fileName, IO.FileMode.Create)
Dim xser As New
System.Xml.Serialization.XmlSerializer(GetType(t))
xser.Serialize(fs, mValue)
End Using

End Sub

Public Sub Load(ByVal fileName As String)

Using fs As New IO.FileStream(fileName, IO.FileMode.Open)
Dim xser As New Xml.Serialization.XmlSerializer(GetType(t))
mValue = DirectCast(xser.Deserialize(fs), t)
End Using

End Sub

Public Sub New(ByVal value As t)
Me.mValue = value
End Sub

Public Sub New()

End Sub
End Class

End Namespace
 
You can also serialize a class to a binary file;

Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Runtime.Serialization

Sub Main
dim InitSet as New InitSettings
'Set properties you want in InitSet
SerializeSettings(InitSet, "MySettingsFileName") ' Serializes settings
to a file
InitSet = DeSerializeSettings("MySettingsFileName") 'Deserializes from
file
End Sub

<Serializable()> Public Class InitSettings
Public MainWindowState As FormWindowState = FormWindowState.Maximized
Public DataBaseFileName As String = ApplicationDataPath & "D&ERecipes.mdb"
Public LastBackUpFileName As String
Public LastMusicSource As Integer
Public LastFileSourcePath As String = "c:\"
Public AudioDisplayIndex As AudioDisplay = AudioDisplay.AvgBitRate
Public DateDisplayIndex As DateDisplay = DateDisplay.YearRecorded
End Class

Public Function SerializeSettings(InitSet as InitSettings, SettingsFileName
as String) As Boolean
Dim s As New MemoryStream
Dim formatter As New BinaryFormatter
Dim rs As New FileStream(SettingsFileName, FileMode.OpenOrCreate)
Try
formatter.Serialize(s, InitSet)
s.WriteTo(rs)
Catch
Return False
Finally
s = Nothing
formatter = Nothing
rs.Close()
rs = Nothing
End Try
Return True
End Function
Private Function DeSerializeSettings(SettingsFileName as String) As
InitSettings
Dim ms As FileStream
Dim formatter As New BinaryFormatter
Try
ms = New FileStream(SettingsFileName, FileMode.Open)
ms.Seek(0, SeekOrigin.Begin)
Return DirectCast(formatter.Deserialize(ms), InitSettings)
Catch
Return nothing
Finally
ms.Close()
formatter = Nothing
End Try
End Function
 
After the objects are loaded, I want to give the user the ability to delete
the entire "project", which is in effect the save file's partening folder.
Only, when I load items using this deserializer, I get an error complaining
that the process cannot access the file because it is in use by another
process. This is strange considering "using" is supposed to explcitly
dispose the file stream after the block has completed execution. Manually
disposing the file stream doesn't help. Any ideas?

Thanks,
Paul
 
Back
Top