|
Site |
Cours VB.net |
|
|
|
Conservation des valeurs; sérialisation. |
|
|
Quand un objet est détruit (fin de programme), les valeurs de ses attributs (les variables) sont perdues!!
Si les valeurs de l'objet changent et doivent être retrouvées lors d'une utilisation ultérieure du programme, il faut les enregistrer.
On pourrait enregistrer chaque attribut dans un fichier séquentiel (FileOpen puis Print..).
On peut aussi utiliser la sérialisation.
La Sérialisation:
La sérialisation est le processus de conversion d'un objet ou d'un groupe d'objets en séquence linéaire d'octets pour stockage ou transmission à un autre emplacement. La désérialisation est le processus consistant à accepter des informations stockées et à recréer des objets à partir de celles-ci.
La sérialisation consiste donc à stocker les valeurs des attributs d'une instance d'un objet dans un fichier qui peut être au format binaire, xml ou Soap.
La sérialisation binaire concerne les champs publics et privés de l'objet et le nom de la classe, y compris l'assembly contenant la classe.
La sérialisation XML ne sérialise que les champs publics et les valeurs des propriétés d'un objet (si elles ne sont pas en lecture seule) dans un flux XML. La sérialisation n'inclut pas d'informations de type.
Lors de la sérialisation, les champs et propriétés sont convertis en un flux d'octets, qui est alors écrit dans un flux de données enregistré sur le disque ou envoyé sur internet.
Lorsque l'objet est ensuite désérialisé,le flux de données venant d'un fichier donne un flux d'octets qui donne une valeur aux champs et propriétés de l'objet, on obtient un objet identique à l'objet d'origine.
Vous pouvez aussi sérialiser un objet et le transporter sur Internet entre un client et un serveur à l'aide du protocole HTTP. À l'autre extrémité, la désérialisation reconstruit l'objet à partir du flux.
Exemple 1: Sérialisation binaire.
Créons une mini Classe:
<Serializable()>
Public Class Compta Public Total As Double Public Taux As DoubleEnd
ClassNotons que pour que la classe soit sérialisable , il faut ajouter <Serializable()>.
L'attribut Serializable indique donc au compilateur que tout ce que contient la classe peut être conservé dans un fichier.
L'attribut NonSerialized peut être utilisé pour marquer les membres de la classe qui ne doivent pas être conservés.
Pour empêcher la sérialisation d'un membre Customer par exemple:
<NonSerialized()> Public Customer As String
Sérialisation:
Dans le corps du programme, il faut mettre:
Imports
System.IOImports
System.Runtime.Serialization.Formatters.binaryDans ce cas, vous utilisez un flux de sortie et un formateur binaire pour enregistrer l'objet dans un format binaire.
Dans l'entête du module créons une objet MyCompta:
Private
myCompta As New ComptaDonnons des valeurs a ses membres.
myCompta.Taux = 2
myCompta.Total = 100
Si on quitte le programme, les valeurs sont perdues!!! On va donc les enregistrer dans un fichier "compta.bin"
Dim myFileStream As Stream = File.Create("Compta.bin")
Dim serializer As New BinaryFormatter
serializer.Serialize(myFileStream, myCompta)
myFileStream.Close()
Et voilà un fichier compta.bin a été crée sur le disque, il contient:
"Bin= ÿÿÿÿ Kserialisation, Version=1.0.1994.38183, Culture=neutral, PublicKeyToken=null serialisation.MaClasse Total Taux Y@ @ "
On a bien enregistré les valeurs des variables d'une instance dans un fichier.
Déserialisation:
Lors de la prochaine utilisation du logiciel,on crée de nouveau une instance de Compta:
Private
myCompta As New ComptaIl faut ensuite 'récupérer' les valeurs de l'instance:
Dans Form1_Load par exemple:
Private Sub Form1_Load()
If File.Exists("Compta.bin") Then
Dim myFileStream As Stream = File.OpenRead("Compta.bin")
Dim deserializer As New BinaryFormatter()
myCompta = CType(deserializer.Deserialize(myFileStream), Compta)
myFileStream.Close()
End If
End Sub
A noter que vous devez d'abord vérifier que le fichier existe. S'il existe, créez une classe Stream pour lire le fichier binaire et une classe BinaryFormatter pour convertir le fichier. La méthode CType est utilisée pour la conversion du type d'objet Stream en type Compta.
Ca marche, on retrouve bien MyCompta.Taux=2
Bien sur , si on sérialise une nouvelle fois, cela écrase le précédent fichier.
Pour les applications Web ou les services Web XML, vous souhaiterez peut-être conserver l'objet dans un fichier XML à l'aide d'un format SOAP, ce qui facilite le partage de l'objet.
il faut charger dans les références la dll .Net System.Runtime.Serialization.Formatters.Soap.dll
Ensuite Imports System.Runtime.Serialization.Formatters.Soap
Dim deserializer As New SoapFormatter
Remplacez
"SavedCompta.bin"
par "SavedCompta.xml".
Cela donne:
Imports
System.IOImports
System.Runtime.Serialization.Formatters.SoapPrivate
MyCompta As New MaClasse
Sérialisation:
MyCompta.Taux = 3
MyCompta.Total = 100
Dim myFileStream As Stream = File.Create("SaveCompta.xml") Dim serializer As New SoapFormatterserializer.Serialize(myFileStream, MyCompta)
myFileStream.Close()
Déserialisation:
Dim
myFileStream As Stream = File.OpenRead("saveCompta.bin") Dim deserializer As New soapFormatterMyCompta =
CType(deserializer.Deserialize(myFileStream), MaClasse)MsgBox(MyCompta.Taux.ToString)
myFileStream.Close()
Si on regarde le fichier SavedCompta.xml (il est dans le répertoire bin) on voit que c'est de l'Xml:
<SOAP-ENV:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:MaClasse id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/serialisation/serialisation%2C%20Version%3D1.0.1995.
30938%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<Total>100</Total>
<Taux>3</Taux>
</a1:MaClasse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
On se rend compte que la sérialisation binaire produit un fichier plus petit.
Exemple 3: Sérialisation d'une collection:
On peut sérialiser un objet, on peut donc sérialiser toutes sortes objets (dit serialisable) , une image, une collection, un tableau....
Une collection est un objet, pour enregistrer son contenu, on peut donc le sérialiser.
Imports System.IO
Imports System.Collections
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Runtime.Serialization
Module MonModule
' Creation d'une hashtable contenant des noms et adresses.
Public addresses As New Hashtable
addresses.Add("Phil", "12 grand rue,69872")
addresses.Add("Bob", "98 petite rue, 196")
addresses.Add("Marie", "BP 89, Paris, 75200")
Sub Serialisation()
' Pour serialiser la hashtable (et les clé/valeur),
Dim fs As New FileStream("MesAdresses.dat", FileMode.Create)
Dim formatter As New BinaryFormatter
Try
formatter.Serialize(fs, addresses)
Catch e As SerializationException
Console.WriteLine("Echec serialisation. Cause: " & e.Message)
Throw
Finally
fs.Close()
End Try
End Sub
Sub Deserialisation()
' Declaration de la HashTable.
Dim addresses As Hashtable = Nothing
Dim fs As New FileStream("DataFile.dat", FileMode.Open)
Try
Dim formatter As New BinaryFormatter
addresses = DirectCast(formatter.Deserialize(fs), Hashtable)
Catch e As SerializationException
Console.WriteLine("Echec de deserialisation. Cause: " & e.Message)
Throw
Finally
fs.Close()
End Try
End Sub
End Module
Exemple 4: Sérialisation d'un tableau:
Private
MyCompta(10) As StringMyCompta(1) = "3"
MyCompta(2) = "100"
Sérialisation:
Dim myFileStream As Stream = File.Create("SaveCompta.xml")
Dim serializer As New SoapFormatter
serializer.Serialize(myFileStream, MyCompta)
myFileStream.Close()
Déserialisation:
Dim
myFileStream As Stream = File.OpenRead("saveCompta.xml") Dim deserializer As New soapFormatterMyCompta =
DirectCast(deserializer.Deserialize(myFileStream), String())MsgBox(MyCompta(1).ToString)
myFileStream.Close()
Vous avez compris. Seule difficulté: le caste en String().
Bien sur, cela marche avec un tableau à plusieurs dimensions. Voyons les lignes à modifier
Private MyCompta(10,10) As String
MyCompta(1,1) = "3"
Dans la déserialisation:
MyCompta = DirectCast(deserializer.Deserialize(myFileStream), String(,))
Exemple 5: Sérialisation d'une collection généric
Ici nous enregistrons les données dans un fichier XML nommé "Meslivres.Xml" (il sera dans le répertoire bin/Debug lors de la conception, et dans le répertoire de l'exécutable si on installe le logiciel).
Les Sub SaveData et LoadData ont en paramètre un type de collection généric list( Of ClasseLivre) C'est une collection d'objets typés ClasseLivre .Ce paramètre est passé avec ByRef .
(Pour l'exemple complet voir le chapitre architecture)
Imports System.Xml.Serialization
Imports System.IO
Public Class AccesAuxDonnees
Public Sub SaveData(ByVal list As Collections.Generic.List(Of ClasseLivre))
' Déclaration
Dim serialXML As Xml.Serialization.XmlSerializer = Nothing
Dim streamIO As StreamWriter = Nothing
Try
serialXML = New Xml.Serialization.XmlSerializer(GetType(Collections.Generic.List(Of ClasseLivre)))
' Ouverture d'un flux en écriture sur le fichier XML des contacts
streamIO = New StreamWriter("Meslivres.Xml")
' Sérialisation de la liste des contacts
serialXML.Serialize(streamIO, list)
Catch ex As Exception
' Propagrer l'exception
Throw ex
Finally
' En cas d'erreur, n'oublier pas de fermer le flux en écriture si ce dernier est toujours ouvert
If streamIO IsNot Nothing Then
streamIO.Close()
End If
End Try
End Sub
Public Sub LoadData(ByRef list As Collections.Generic.List(Of ClasseLivre))
' Déclaration
Dim streamIO As StreamReader = Nothing
Dim serialXML As Xml.Serialization.XmlSerializer = Nothing
Try
' Tester l'existance du fichier
If System.IO.File.Exists("Meslivres.Xml") = True Then
serialXML = New Xml.Serialization.XmlSerializer(GetType(Collections.Generic.List(Of ClasseLivre)))
' Ouverture d'un flux en lecture sur le fichier XML des contacts
streamIO = New StreamReader("Meslivres.Xml")
' Désérialisation de la liste des contacts
list = CType(serialXML.Deserialize(streamIO), Collections.Generic.List(Of ClasseLivre))
End If
Catch ex As Exception
' Propagrer l'exception
Throw ex
Finally
' En cas d'erreur, n'oublier pas de fermer le flux en lecture si ce dernier est toujours ouvert
If streamIO IsNot Nothing Then
streamIO.Close()
End If
End Try
End Sub
End Class
Voila ce que donne le fichier XMl:
<?xml version="1.0"
encoding="utf-8"?>
<ArrayOfClasseLivre xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ClasseLivre>
<Titre>Livre1</Titre>
<Auteur>Auteur1</Auteur>
</ClasseLivre>
<ClasseLivre>
<Titre>Livre2</Titre>
<Auteur>Auteur2</Auteur>
</ClasseLivre>
<ClasseLivre>
<Titre>Titre3</Titre>
<Auteur>Auteur3</Auteur>
</ClasseLivre>
</ArrayOfClasseLivre>
|
|
|
|
|