ThinkGeo.com    |     Documentation    |     Premium Support

How to serialize multiple layers in a single file

Guys,


I have been using .NET binary serialization to save/restore the state of the map. This approach works great until we download a new set of dll's from the daily build and some change in one of the classes causes existing files no longer to load because of compatibility issues in the newer version.


Since ThinkGeo has now released the GeoSerializer (which is supposed to solve the compatibilty issue) I would like to switch to that method. However, if I try to serialize more than one layer to the file I receive an error when trying to deserialize:



System.Xml.XmlException was unhandled
  LineNumber=122
  LinePosition=27
  Message=Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it. Line 122, position 27.
  Source=System.Xml
  SourceUri=""
  StackTrace:
       at System.Xml.XmlTextReaderImpl.Throw(Exception e)
       at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
       at System.Xml.XmlTextReaderImpl.ParsePI(StringBuilder piInDtdStringBuilder)
       at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
       at System.Xml.XmlTextReaderImpl.Read()
       at ThinkGeo.MapSuite.Core.XmlGeoSerializationFormatter.xBQ=(XmlReader 4RU=)
       at ThinkGeo.MapSuite.Core.XmlGeoSerializationFormatter.LoadCore(Stream stream)
       at ThinkGeo.MapSuite.Core.GeoSerializationFormatter.Load(Stream stream)
       at ThinkGeo.MapSuite.Core.GeoSerializer.Deserialize(Stream sourceStream)
       at SerializeProjectedLayer.Form1.DeSerializeShapefile() in C:\Users\steller\Documents\Visual Studio 2010\Projects\ThinkGeo\SerializeProjectedLayer\Form1.vb:line 99
       at SerializeProjectedLayer.Form1.btnDeserialize_Click(Object sender, EventArgs e) in C:\Users\steller\Documents\Visual Studio 2010\Projects\ThinkGeo\SerializeProjectedLayer\Form1.vb:line 165
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at SerializeProjectedLayer.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

I have attached a sample project so you can see exactly what my code is doing. What can I do to fix this?


Thanks,


Steve



SerializeShapefiles.zip (27.6 KB)

Hi Steven,


We apologize for the delay and any inconvenience this may cause. 



Thanks for your detailed information of this issue, I checked the demo code you provided, seems  that you saved 2 serialized ShapeFileLayer string into a single file “Shapefile.wxd”, I think this should be the problem, actually, if we call “GeoSerializer.Serializer()” once, it will generate a complete Xml string which starts with “<?xml version="1.0" encoding="utf-8"?>”, if twice, it will generate 2 copy of complete XMl string, in other words, if we check the content of the “Shapefile.wxd”, it should be as following, it’s not allowed:






There are 2 ways to resolve the problem:

        1.Serialize different layer into different “.wxd” file. 

        2.Serialize and de-serialize 2 layers at the same time.




Best Regards!

Johnny

 



Johnny, 



Thanks for your response. I was afraid that was what you were going to say.  



In order for serialization to be useful to us, we must be able to serialize the entire 'Workspace' into a single file. Our 'Workspace' consists of one or more maps, one or more 'Page Layout' maps and the layers in the maps. When restoring a 'session' we don't want to have to read several different files, but just one. The idea of us being able to serialize a session into a file that would still be usable when new versions of MS Desktop become available is very appealing. Many times when we move to a newer version the existing files we created from binary serialization will no longer work properly. 



Would it be possible for ThinkGeo to provide a method (in some future version) to serialize everything to a single file? 



Thanks! 



Steve



Steven, 
  
   One thing that we do in our Gis Editor is that we also want one file for portability and such.  How we handle this is we use a popular zip library that allows us to have one zip file that contains multiple other files inside.  Since it supports sub directories directories you can easily organize the data within however you want.  The great part is that you can insert, remove, read and modify data inside the zip file using streams so there is never any reason to actually open the file on the disk.  The program sees it as separate files but its all together.   
  
   In our product when you save a project we have just one file but that file contains the complete map control serialized, it contains a thumbnail snapshot of the map, for preview purposed, it contains a bunch of XML files as well for setting and could even contain data files if we wanted or just about anything.  The other nice thing about this is that if push comes to show and a user sent us his project we could unzip it, could also support passwords. :-), and we can look at all the XML files, make modification and send it back.  One reason I suggest separate XML files is that if you put settings, map state etc in one file it is more likely there will be a problem where your XML is not well formed and it makes your recovery that much harder.  Separate files isolates issues and allows you to possibly recover parts of a project even if other parts fail. 
  
   Ok, maybe way more than what you were thinking but I wanted to share. 
  
 David

Hi David, 
  
 Thanks for your response, you make some very good points, and it gives me a different way to think about it. 
  
 Steve

David, I’m just  a lurker on this, but I really like what you have described here, too.   I’m especially interested in exploring the ability to stream directly from a the zip files as we move lots of data around with the zipping engine that we use.

Ted, 
  
   I am pretty sure we use SharpZipLib which is free and pretty easy to use.  We may have replaced it but I’m not sure and will check on that.  The nicest thing is portability of a bunch of semi related items.  Also if push comes to shove I can unzip it and get to all the content.  Also the password protection piece is nice as well as well as the side effect of compression.  The one thing that is not that nice is that the streams are not random access so you read or write the whole file at a time.  You can’t really go in and modify a part of a file.  This is ok for state and setting but for data we need to unpack it and set it up somewhere temporary. 
  
 David

We’ve used SharpZipLib since we started programming in .Net.   But recently shifted to some 7z free library.   On our kind of data, the improved compression was really amazing.

Ted, 
  
   7z is the compression king for sure, I didn’t know they had a .net library though.  :-)  Always a pleasure chatting with you Ted! 
  
 David

Guys, 
  
 I have been using 7z and it’s the best tool for creating zip files (and other types) I’ve ever used, and free to boot. I’ve only used the graphical front end, but now I’ll probably investigate implementing some of your suggestions, David. Thanks, guys, for the ideas. 
  
 Steve

Hello Steven, 
  
 If you still meet any problems, don’t hesitate to let us know. 
  
 Regards, 
  
 Gary