Saving multiple files into one

XML data and pictures in the same file

Page 1 of 1

5 Replies - 3684 Views - Last Post: 15 October 2007 - 11:21 PM Rate Topic: -----

#1 aceofspades686  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 6
  • View blog
  • Posts: 334
  • Joined: 08-October 07

Saving multiple files into one

Post icon  Posted 14 October 2007 - 10:49 PM

I'm reached another bump in the road on my membership program, and I can't seem to find any resources linking to what I want to do.

The problem is this, within my program, I have a class that holds all the info for members, then on save, exports it to an .xml file. This part works fine for everything but the pictures. What I would like to do is save the pictures in the same file as the xml data, that way there wouldn't be any worry about directory structure or file dependencies for each member. Also, how would I reference the pictures within the xml data (or would I at all)? I'm at a severe loss as to how to go about this and all I can manage to find are downloads for compression programs (ala winzip, winrar, 7-zip, etc.).

And of course, I'm not looking for a hand out. Just something to nudge me in the right direction so I can find the information to figure it out. Thanks in advance to anyone who can help me out.

EDIT: Here's my current XML handler class if that helps any. Also, if anyone knows a better way to go about this, feel free to tell me. I'm not against trying a different method since this was my first attempt at dealing with XML files (other than writing them by hand for things like RSS feeds and such).

Imports System.Xml
Public Class XMLHandler
#Region "Class Variables"
	Private _sPath As String
#End Region
#Region "Class Properties"
	Public Property Path() As String
		Get
			Return _sPath
		End Get
		Set(ByVal value As String)
			_sPath = value
		End Set
	End Property
#End Region
#Region "Class Methods"
	Public Sub New()
	End Sub

	Public Sub Read(ByRef oMembersCollection As MemberCollection, ByRef oFeeCollection As FeeCollection, _
		ByRef oAttendanceCollection As AttendanceCollection)
		Dim XMLRead As New XmlTextReader(Me.Path)
		XMLRead.WhitespaceHandling = WhitespaceHandling.None
		Try
			Do Until XMLRead.Name = "Club"
				XMLRead.Read()
			Loop
			XMLRead.ReadStartElement("Club")
			Do Until (XMLRead.Name = "Club" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
				Do Until XMLRead.Name = "Members"
					XMLRead.Read()
				Loop
				XMLRead.ReadStartElement("Members")
				Do Until (XMLRead.Name = "Members" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
					Do Until XMLRead.Name = "Member"
						XMLRead.Read()
					Loop
					Dim iID As Integer
					iID = Convert.ToInt32(XMLRead.Item("ID"))
					Dim oMember As New Member(iID)
					XMLRead.ReadStartElement("Member")
					Do Until (XMLRead.Name = "Member" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
						oMember.FirstName = XMLRead.ReadElementString("FirstName")
						oMember.MiddleName = XMLRead.ReadElementString("MiddleName")
						oMember.LastName = XMLRead.ReadElementString("LastName")
						oMember.NickName = XMLRead.ReadElementString("NickName")
						oMember.Address = XMLRead.ReadElementString("Address")
						oMember.City = XMLRead.ReadElementString("City")
						oMember.State = XMLRead.ReadElementString("State")
						oMember.ZipCode = Convert.ToInt32(XMLRead.ReadElementString("Zip"))
						oMember.Phone1 = XMLRead.ReadElementString("Phone1")
						oMember.Phone2 = XMLRead.ReadElementString("Phone2")
						oMember.EMail = XMLRead.ReadElementString("EMail")
						oMember.MemberType = XMLRead.ReadElementString("Type")
						oMember.Joined = Convert.ToDateTime(XMLRead.ReadElementString("DateJoined"))
						oMember.DateofBirth = Convert.ToDateTime(XMLRead.ReadElementString("Birthdate"))
						oMember.DatePaymentDue = Convert.ToDateTime(XMLRead.ReadElementString("Paymentdue"))
						oMember.PictureURI = XMLRead.ReadElementString("Picture")
						oMember.Notes = XMLRead.ReadElementString("Notes")
						oMembersCollection.Add(oMember)
					Loop
					XMLRead.ReadEndElement()
				Loop
				XMLRead.ReadEndElement()

				Do Until XMLRead.Name = "Attendance"
					XMLRead.Read()
				Loop
				XMLRead.ReadStartElement("Attendance")
				Do Until (XMLRead.Name = "Attendance" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
					Do Until XMLRead.Name = "Meeting"
						XMLRead.Read()
					Loop
					Dim oAttendanceMeeting As New AttendanceMeetings
					Dim dMeeting As Date
					Dim iID As Integer
					dMeeting = Convert.ToDateTime(XMLRead.Item("Date"))
					XMLRead.ReadStartElement("Meeting")

					oAttendanceMeeting.MeetingDate = dMeeting
					Do Until (XMLRead.Name = "Meeting" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
						iID = Convert.ToInt32(XMLRead.ReadElementString("Attended"))
						Dim oAttendance As New Attendance(iID)
						oAttendanceMeeting.Add(oAttendance)
					Loop
					oAttendanceCollection.Add(oAttendanceMeeting)
					XMLRead.ReadEndElement()
				Loop
				XMLRead.ReadEndElement()

				Do Until XMLRead.Name = "Fees"
					XMLRead.Read()
				Loop
				XMLRead.ReadStartElement("Fees")
				Do Until (XMLRead.Name = "Fees" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
					Do Until XMLRead.Name = "Meeting"
						XMLRead.Read()
					Loop
					Dim oFeeMeeting As New FeeMeetings()
					Dim dMeeting As Date
					dMeeting = Convert.ToDateTime(XMLRead.Item("Date"))
					oFeeMeeting.MeetingDate = dMeeting
					XMLRead.ReadStartElement("Meeting")
					Do Until (XMLRead.Name = "Meeting" AndAlso XMLRead.NodeType = XmlNodeType.EndElement)
						Dim oFee As New Fee()
						Do Until XMLRead.Name = "Member"
							XMLRead.Read()
						Loop
						oFee.MemberID = Convert.ToInt32(XMLRead.Item("ID"))
						XMLRead.ReadStartElement("Member")
						oFee.AmountPaid = Convert.ToDouble(XMLRead.ReadElementString("Amount"))
						oFeeMeeting.Add(oFee)
						XMLRead.ReadEndElement()
					Loop
					XMLRead.ReadEndElement()
					oFeeCollection.Add(oFeeMeeting)
				Loop
				XMLRead.ReadEndElement()
			Loop
			XMLRead.ReadEndElement()
			XMLRead.Close()

		Catch ex As XmlException
			MessageBox.Show("There is an Error in the XML File." & ControlChars.CrLf & ex.ToString, "XML Error")
		End Try
	End Sub
	Public Sub Save(ByVal oMembers As MemberCollection, ByVal oFeesCollection As FeeCollection, ByVal oAttendanceCollection As AttendanceCollection)

		Dim XMLSave As New XmlTextWriter(Me.Path, Nothing)
		Dim oMember As Member
		Dim oAttendanceMeeting As AttendanceMeetings
		Dim oAttendance As Attendance
		Dim oFeesMeeting As FeeMeetings
		Dim oFees As Fee

		XMLSave.Formatting = Formatting.Indented
		XMLSave.WriteStartDocument()
		XMLSave.WriteStartElement("Club")
		XMLSave.WriteStartElement("Members")
		For Each oMember In oMembers
			XMLSave.WriteStartElement("Member")
			XMLSave.WriteAttributeString("ID", oMember.MemberID.ToString)
			XMLSave.WriteElementString("FirstName", oMember.FirstName)
			XMLSave.WriteElementString("MiddleName", oMember.MiddleName)
			XMLSave.WriteElementString("LastName", oMember.LastName)
			XMLSave.WriteElementString("NickName", oMember.NickName)
			XMLSave.WriteElementString("Address", oMember.Address)
			XMLSave.WriteElementString("City", oMember.City)
			XMLSave.WriteElementString("State", oMember.State)
			XMLSave.WriteElementString("Zip", oMember.ZipCode.ToString)
			XMLSave.WriteElementString("Phone1", oMember.Phone1.ToString)
			XMLSave.WriteElementString("Phone2", oMember.Phone2.ToString)
			XMLSave.WriteElementString("EMail", oMember.EMail)
			XMLSave.WriteElementString("Type", oMember.MemberType)
			XMLSave.WriteElementString("DateJoined", oMember.Joined.ToShortDateString)
			XMLSave.WriteElementString("Birthdate", oMember.DateofBirth.ToShortDateString)
			XMLSave.WriteElementString("Paymentdue", oMember.DatePaymentDue.ToShortDateString)
			XMLSave.WriteElementString("Picture", oMember.PictureURI)
			XMLSave.WriteElementString("Notes", oMember.Notes)
			XMLSave.WriteEndElement()
		Next
		XMLSave.WriteEndElement()
		XMLSave.WriteStartElement("Attendance")
		For Each oAttendanceMeeting In oAttendanceCollection
			XMLSave.WriteStartElement("Meeting")
			XMLSave.WriteAttributeString("Date", oAttendanceMeeting.MeetingDate.ToShortDateString)
			For Each oAttendance In oAttendanceMeeting
				XMLSave.WriteElementString("Attended", oAttendance.MemberID.ToString)
			Next
			XMLSave.WriteEndElement()
		Next
		XMLSave.WriteEndElement()
		XMLSave.WriteStartElement("Fees")
		For Each oFeesMeeting In oFeesCollection
			XMLSave.WriteStartElement("Meeting")
			XMLSave.WriteAttributeString("Date", oFeesMeeting.MeetingDate.ToShortDateString)
			For Each oFees In oFeesMeeting
				XMLSave.WriteStartElement("Member")
				XMLSave.WriteAttributeString("ID", oFees.MemberID.ToString)
				XMLSave.WriteElementString("Amount", oFees.AmountPaid.ToString)
				XMLSave.WriteEndElement()
			Next
			XMLSave.WriteEndElement()
		Next
		XMLSave.WriteEndElement()
		XMLSave.WriteEndElement()
		XMLSave.Close()
	End Sub
#End Region
End Class



EDIT2: After digging a little deeper in the MSDN Library, I think I may have found the solution in the XMLTextWriter.WriteBase64 method. I'm going to try to attempt to implement this and if it works I'll post the resulting code.

This post has been edited by aceofspades686: 15 October 2007 - 04:34 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Saving multiple files into one

#2 aceofspades686  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 6
  • View blog
  • Posts: 334
  • Joined: 08-October 07

Re: Saving multiple files into one

Posted 15 October 2007 - 05:57 AM

No luck with this so far. I've tried using the XMLTextWriter.WriteBase64 method, but even if an image is set to the property, it writes nothing to the file.

Here is the code I added to handle the .writebase64
			If Not (oMember.Picture Is Nothing) Then
				Dim imagestream As New System.IO.MemoryStream
				Dim filetype As Imaging.ImageFormat = oMember.Picture.RawFormat
				Dim bufferSize As Integer = 1000
				Dim buffer(bufferSize) As Byte
				Dim readBytes As Integer = 0
				oMember.Picture.Save(imagestream, filetype)
				XMLSave.WriteStartElement("Picture")
				Dim br As New System.IO.BinaryReader(imagestream)
				Do
					readBytes = br.Read(buffer, 0, bufferSize)
					XMLSave.WriteBase64(buffer, 0, readBytes)
				Loop While bufferSize <= readBytes
				br.Close()
				XMLSave.WriteEndElement()
			Else
				XMLSave.WriteElementString("Picture", String.Empty)
			End If


  If Not XMLRead.IsEmptyElement = Nothing Then
							Dim imageout As New System.IO.MemoryStream
							Dim bw As New System.IO.BinaryWriter(imageout)
							Dim buffer(999) As Byte
							Dim readBytes As Integer = 0
							readBytes = XMLRead.ReadElementContentAsBase64(buffer, 0, 50)
							While (readBytes > 0)
								bw.Write(buffer, 0, readBytes)
								readBytes = XMLRead.ReadElementContentAsBase64(buffer, 0, 50)
							End While
							bw.Close()
						Else
							XMLRead.ReadElementString("Picture")
						End If



That's admittedly copied straight from the MSDN examples. I'm such a noob when it comes to working with files outside of basic textfiles.
Was This Post Helpful? 0
  • +
  • -

#3 m2s87  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 21
  • View blog
  • Posts: 390
  • Joined: 28-November 06

Re: Saving multiple files into one

Posted 15 October 2007 - 06:30 AM

nudge - use database; something like:
Was This Post Helpful? 0
  • +
  • -

#4 aceofspades686  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 6
  • View blog
  • Posts: 334
  • Joined: 08-October 07

Re: Saving multiple files into one

Posted 15 October 2007 - 05:19 PM

View Postm2s87, on 15 Oct, 2007 - 09:30 AM, said:

nudge - use database; something like:

Biggest reason I don't want to use a database is we don't have any centrally located servers (at least secure) and the files do contain some sensitive data. I know I could use access but it tends to be slow, and this makes it easier for me to encrypt the files and keep a master copy on a web server.
Was This Post Helpful? 0
  • +
  • -

#5 aceofspades686  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 6
  • View blog
  • Posts: 334
  • Joined: 08-October 07

Re: Saving multiple files into one

Posted 15 October 2007 - 07:07 PM

I've figured out where the problem is, just not how to fix it.

Dim br As New System.IO.BinaryReader(imagestream)
Do
	readBytes = br.Read(buffer, 0, bufferSize)
	XMLSave.WriteBinHex(buffer, 0, readBytes)
Loop While (bufferSize <= readBytes)
br.Close()



Even on first read-through, readBytes is returning as 0. Is my BinaryReader just not reading the data from the stream? I've checked the stream by making the image in it output to another window from stream, so I know the image is there.

EDIT: I've been switching back and forth between .WriteBase64 and .WriteBinHex to see if that would make a difference but so far nothing is showing up with either.

This post has been edited by aceofspades686: 15 October 2007 - 07:57 PM

Was This Post Helpful? 0
  • +
  • -

#6 aceofspades686  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 6
  • View blog
  • Posts: 334
  • Joined: 08-October 07

Re: Saving multiple files into one

Posted 15 October 2007 - 11:21 PM

Figuring it out by going a different way about it. Posting the code here in case anyone else runs into the same trouble.

Code to read it:
Dim pic As String
	 pic = XMLRead.ReadElementString("Picture")
	 If Not pic = String.Empty Then
		  Dim imagebuffer As Byte() = Convert.FromBase64String(pic)
		  oMember.Picture = Image.FromStream(New System.IO.MemoryStream(imagebuffer))
	 End If


Code to write it:
If Not (oMember.Picture Is Nothing) Then
	 Dim imagestream As New System.IO.MemoryStream
	 Dim filetype As Imaging.ImageFormat = oMember.Picture.RawFormat
	 
	 oMember.Picture.Save(imagestream, filetype)
	 XMLSave.WriteStartElement("Picture")
	 XMLSave.WriteBase64(imagestream.GetBuffer(), 0, imagestream.Length)
	 XMLSave.WriteEndElement()
Else
	 XMLSave.WriteElementString("Picture", String.Empty)
End If



Notes on the code:
  • oMember in both cases is a custom object that hold various information about members.
  • The oMember.Picture Property is of the type System.Drawing.Image and as such, you must add a reference to the System.Drawing namespace.
  • XMLRead is an instance of the XMLTextReader Class.
  • XMLSave is an instance of the XMLTextWriter Class
  • Both the XMLTextReader and the XMLTextWriter classes require a reference to the System.XML namespace.

I think that's the only things I needed to mention. If I realize I forgot something I'll edit it in.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1