Scrivere oggetti in codifica binaria trova grande utilità quando dobbiamo salvare delle immagini per esempio in un database, stessa cosa possiamo fare con un file XML che per sua natura può essere trasferito tramite Web Service, o anche tramite rete senza problemi, ed essere letto da qualunque linguaggio.
La scrittura su file XML avviene tramite la codifica
Base64 e rispetta le specifiche
RCF 1521, per vedere tali specifiche potete consultarle qui:
http://www.ietf.org/rfc/rfc1521.txt ">RFC 1521.
Per comodità ma anche per maggior utilizzo useremo le Win Forms ma nessuno ci vieta di utilizzare tale procedura anche con le Web Forms.
Iniziamo, e per prima cosa creiamo un nuovo progetto, al primo Form aggiungiamo una
PictureBox e impostiamo un'immagine a piacimento.
Vediamo ora il codice per scrivere:
Per prima cosa importiamo i
Namespaces che ci servono per l'applicazione.
Imports System.IO
Imports System.Drawing
Imports System.Xml
Poi aggiungiamo questo codice ad una Sub:
'apro lo stream per il file
Dim fs As New FileStream("Immagine.xml", FileMode.Create)
Dim writer As New XmlTextWriter(fs, System.Text.Encoding.UTF8)
writer.Formatting = Formatting.Indented
'inizializzo il documento xml
writer.WriteStartDocument()
writer.WriteStartElement("Root")
writer.WriteStartElement("Immagine")
Come si vede anche dal codice apro lo stream per creare il file XML, poi istanzio la classe
XmlTextWriter con lo
Stream e la codifica utilizzata nel nostro caso utilizziamo la
UTF8.
Poi formattiamo il file(
Formatting.Indented) e creiamo il tag iniziale
"Root" ed un tag figlio
"Immagine".
Poi molto importante è recuperare i byte che formano l'immagine, quindi dichiaro un'array di byte che avrà come valore la restituzione della function GetByte:
Dim aByte() As Byte = GetByte()
Vediamo cosa fa la function
GetByte:
Private Function GetByte() As Byte()
Dim ms As New MemoryStream()
Dim bt As New Bitmap(Me.pcBox.Image)
bt.Save(ms, Imaging.ImageFormat.Jpeg)
Return ms.ToArray
End Function
Creo un nuovo oggetto dalla classe
MemoryStream così da non dover salvare niente sul locale(davvero utile), poi creo una nuova Immagine(
Bitmap) partendo da quella presente sul form(Me.pcBox.Image), poi salvo l'immagine nel MemoryStream e infine utilizzo il metodo
ToArray che restituisce un array di byte.
Una volta recuperati i byte dell'immagine mi segno la dimensione per poi poterli recuperare quando li leggo e li segno su un attributo in questo modo:
writer.WriteAttributeString("Count", aByte.Length.ToString)
E poi scrivo I byte utilizzando il metodo WriteBase64:
writer.WriteBase64(aByte, 0, aByte.Length)
Questo metodo come parametri vuole:
? Un?array di byte? L?indice da dove iniziare a scrivere? Il numero di byte da scrivereInfine chiudiamo i due tag, il documento, il
Writer e per ultimo lo
Stream:
writer.WriteEndElement()
writer.WriteEndElement()
writer.WriteEndDocument()
writer.Flush()
writer.Close()
fs.Close()
Ora vediamo come leggere l'immagine inserita nel file XML.
Quindi per comodità utilizziamo lo stesso progetto, inseriamo un altro form e aggiungiamo anche qui una PictureBox. I Namespaces da importare sono gli stessi di sopra.
Quindi nel
Load del form andiamo a leggere l'immagine:
Dim fs As New FileStream("Immagine.xml", FileMode.Open, FileAccess.Read)
Dim reader As New XmlTextReader(fs)
'leggo il nodo dove si trova l'immagine
While reader.Read
If reader.Name = "Immagine" Then
Exit While
End If
End While
Anche qui imposto lo
Stream questa volta per leggere, e istanzio la classe
XmlTextReader che rappresenta un visualizzatore che fornisce accesso veloce, non in cache e di tipo forward-only ai dati XML.
Quindi scorro il file finché non trovo il nodo
"Immagine" e quindi posso uscire dal ciclo.
Quindi recupero il valore dell?attributo
"Count" in cui ci sono le dimensioni del file
"Immagine":
Dim count As Integer = CType(reader.Item(0), Integer)
E poi recupero i byte dell'immagine utilizzando il metodo
ReadBase64 che decodifica appunto i byte scritti in
Base64
Dim indice As Integer = 0
Dim aByte(count) As Byte
indice = reader.ReadBase64(aByte, 0, count)
il metodo
ReadBase64 è una Function che restituisce un'Integer e come parametri vuole
? Il buffer dove scrivere i byte decodificati? L?indice da dove iniziare a scrivere? Il numero di byteCome vedete l'ultimo parametro è il numero di byte da scrivere per questo è molto importante salvarsi la dimensione del file in fase di scrittura.
Infine chiudo il
Reader e lo
Stream:
reader.Close()
fs.Close()
Come ultima cosa devo assegnare il file immagine alla mia PictureBox:
Dim ms As New MemoryStream()
ms.Write(aByte, 0, count)
'assegno alla picture box l'immagine presa dal memorystream
pcRead.Image = Image.FromStream(ms)
ms.Close()
Come vedete utilizzo di nuovo il
MemoryStream per non scrivere niente in locale.
Nei file allegati all'articolo trovate lo script di lettura e scrittura anche in linguaggio
C#.
ConclusioniQuesto articolo vuole far vedere se ancora ce ne bisogno la potenza dello standard XML e come utilizzare le classi
XmlTextWriter e
XmlTextReader e come attraverso la classe
MemoryStream non si debba salvare niente in locale, velocizzando di fatto l'esecuzione del codice non essendoci accesso a disco.