• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
bobird的学习笔记
博客园    首页    新随笔    联系   管理    订阅  订阅

ArcEngine 序列化和反序列化

‍相关网址:http://www.cnblogs.com/wall/archive/2009/02/26/1398447.html

                 http://www.gisall.com/html/77/27977-1183.html

                http://blog.csdn.net/yanleigis/article/details/4770267

ArcEngine 中有很多对象是可以序列化,凡是实现了‍IPersistStream接口的对象都可序列化,序列化之后的好处呢有很多,比如:你可以将Ilayer,IfeatureLayer,Irasterlayer,ifeatureSender....等等序列化之后存为文件保存起来,或者是将序列化之后的对象转为字节数组存到数据库中保存,上述对象一般都是存有图层的信息,存起来之后有利于我们调用各种显示效果。ArcEngine 中对象属于COM对象,当我们在做多线程程序处理GIS数据的时候这些COM对象是不能轻易的在线程间传递的,此时我们就能利用AE提供的序列化功能将这些COM对象序列化为自己数组或是文件来达到线程间数据共享的目的。

一、‍AE对象序列化后转成字节数组和从字节数组反序列化为AE对象

         1、AE对象序列化后转成字节数组


        /// <summary>
        /// 将传入的AE对象序列化成byte数组
        /// </summary>
        /// <param name="objData">要序列化的数据</param>
        /// <param name="type">序列化的类别,0:rasterlayer,1:featurelayer</param>
        private byte[] CreateByteFromObjData(object objData,int type)
        {
                //Engine中的BlobStream对象
                IMemoryBlobStream pBlobStream = new MemoryBlobStream();

               ‍ //将传入的对象转为‍IPersistStream

                IPersistStream pPerStreamout = (IPersistStream)objData;

                //存入BlobStream
                pPerStreamout.Save(pBlobStream, 0);

                //转换为Variant类型          
                IMemoryBlobStreamVariant pVar = (IMemoryBlobStreamVariant)pBlobStream;

                object pobj = new object();

                //转入Object对象

                pVar.ExportToVariant(out pobj);

                //强制转换为Byte数组,并返回
                byte[] tempRaster = pobj as byte[]; 

               return    ‍tempRaster ;           
        }

         2、‍从字节数组反序列化为AE对象


‍        /// <summary>
        /// 将byte数组反序列化为AE对象

        /// </summary>
        ///<param name="type">反序列化类型,0:irasterlayer,1:Ifeaturelayer</param>
        private IPersistStream GetRasterLayerFromByte(‍byte[] tempByte )
        {
            IMemoryBlobStream pBlobStream = new MemoryBlobStreamClass();

            IMemoryBlobStreamVariant pVar = (IMemoryBlobStreamVariant)pBlobStream;
            IPersistStream pPerStreamout = null;
             object pobj = tempByte as object;

               //从Byte数据读取数据

              pVar.ImportFromVariant(pobj);

               //根要转换的类型创建不同的‍IPersistStream 对象

              pPerStreamout = new RasterLayerClass();

               //载入数据,并强制转换为ILayer类型

              pPerStreamout.Load(pBlobStream);
               return pPerStreamout;
         }

返回的是一个IPersistStream ,根据你在代码中创建的‍IPersistStream在接口查询到要使用的接口

‍

二、‍AE对象序列化后存为文件和从文件反序列化为AE对象

        /// <summary>
        /// 序列化AE对象
        /// </summary>
        /// <param name="gisObj"></param>
          private void SerializeArcGisObject(object gisObj)
          {
               //转换成IPersistStream对象
               IPersistStream ps = gisObj as IPersistStream;
                //如果是继承了IPersistStream接口,则序列化
              if (ps != null)
               {
                       定义一种流对象;这里使用了MemoryBlobStreamClass
                         MemoryBlobStreamClass mbsc = new MemoryBlobStreamClass();
                        //把对象保存到流中
                        ps.Save(mbsc, 0);
                       //保存成文件
                        mbsc.SaveToFile(path);
                  }
           }

 

‍        private IRasterLayer DeserializeArcGisObject(string filename, IRasterLayer rasterLayer)
        {

            //定义一种流对象;这里使用了MemoryBlobStreamClass

            //使用流读取文件

            IBlobStream mbsc = new MemoryBlobStreamClass();

            //使用流读取文件

            mbsc.LoadFromFile(path);
            IObjectStream pObjectStream=new ObjectStreamClass();
            pObjectStream.Stream = mbsc as IStream;
            ESRI.ArcGIS.esriSystem.IPersistStream ips = rasterLayer as IPersistStream;
            ips.Load(pObjectStream as IStream);
            return rasterLayer;

        }

三、序列化为XML(从网上刮来的,还未用过)

 

‍

1.序列化和反序列化Geometry对象

public void TestSrializePoint()

{

IPoint pPoint = new PointClass();

pPoint.X = 10;

pPoint.Y = 10;

IXMLStream pStream = new XMLStreamClass();

IXMLWriter pWriter = new XMLWriterClass();

pWriter.WriteTo((IStream) pStream);

IXMLSerializer pSerializer = new XMLSerializerClass();

pSerializer.WriteObject(pWriter, null, null, "", "", pPoint);

pStream.SaveToFile("C:\\Point.XML");

IXMLStream pStream2 = new XMLStreamClass();

pStream.LoadFromFile("C:\\Point.XML");

IXMLReader pReader = new XMLReaderClass();

pReader.ReadFrom( (IStream)pStream);

IXMLSerializer pSerializer2 = new XMLSerializerClass();

IPoint point = (IPoint)pSerializer2.ReadObject(pReader, null, null);

MessageBox.Show(point.SpatialReference.Name);

}

2.序列化和反序列化IRecordset对象

/// <summary>

/// 将一个FeatureClass中指定范围的Recordset序列化成XML文档

/// </summary>

/// <param name="featureClass"></param>

public void WriteXMLToDisk(IFeatureClass featureClass)

{

string ss= "http://www.esri.com/schemas/ArcGIS/9.0"; ;

IPropertySet pPropset = new PropertySetClass();

pPropset.SetProperty( "Namespaceuri", "http://schemas.esri.com/ArcGis/Server/");

IPropertySet pCpropset = new PropertySetClass();

pCpropset.SetProperty("http://schemas.esri.com/ArcGis/Server/", "xmlns");

pPropset.SetProperty ("Namespaceprefixes", pCpropset);

//IFeatureClass featureClass=featureLayer.FeatureClass;

IRecordSetInit recordSetInit=new RecordSetClass();

IRecordSet recordSet;

IQueryFilter queryFilter = new QueryFilterClass();

//queryFilter.SubFields = "Shape";

queryFilter.WhereClause = "FID=22";

recordSetInit.SetSourceTable((ITable)featureClass, queryFilter);

recordSet = (IRecordSet)recordSetInit;

IXMLStream xmlStream = new XMLStreamClass();

IXMLWriter xmlWriter = new XMLWriterClass();

xmlWriter.WriteTo((IStream)xmlStream);

IXMLSerializer XmlSerializer = new XMLSerializerClass();

try

{

XmlSerializer.WriteObject(xmlWriter, pPropset, null, "Record", ss, recordSet);

xmlStream.SaveToFile("C:\\Record.xml");

}

catch (System.Runtime.InteropServices.COMException ex)

{

throw new ArgumentException(ex.Message);

}

finally

{

GC.Collect();

}

}

/// <summary>

/// 将序列化的IRecodset文本反序列化成一个IRecordset对象

/// </summary>

/// <param name="strXmlPath"></param>

/// <returns></returns>

public IRecordSet ReadXmlFromDisk(string strXmlPath)

{

IXMLStream XmlStream = new XMLStreamClass();

XmlStream.LoadFromFile(strXmlPath);

IXMLReader XmlReader = new XMLReaderClass();

XmlReader.ReadFrom((IStream)XmlStream);

IXMLSerializer XmlSerializer = new XMLSerializerClass();

IRecordSet recordSet = (IRecordSet)XmlSerializer.ReadObject(XmlReader, null, null);

return recordSet;

}

 

http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=109590&extra=page%3D5%26amp%3Bfilter%3Dtype%26amp%3Btypeid%3D4

以前做惟一值渲染时,为满足特定应用,曾想将每个要素对应的Symbol存入该要素字段中,当时考虑到Field Type中有一个Blob类型,美美地想如果将Symol转化成了Blob,岂不大功告成?在DevelopHelp中翻江倒海,欣喜地发现了IPersistStream这个接口,顺藤摸瓜找到了IMemoryBlobStream, 立马打开VS,敲码如下:
        public void SaveSymbolToField(IFeature feature, string field, ISimpleLineSymbol symbol)
        {
            IPersistStream persistStream = symbol as IPersistStream;
            IMemoryBlobStream memoryBlobStream = new MemoryBlobStreamClass();
            persistStream.Save(memoryBlobStream, 0);
            int index = feature.Fields.FindField(field);
            feature.set_Value(index, memoryBlobStream);
            feature.Store();
        }

        public ISimpleLineSymbol ReadSymbolFromField(IFeature feature, string field)
        {
            int index = feature.Fields.FindField(field);
            IMemoryBlobStream memoryBlobStream = feature.get_Value(index) as IMemoryBlobStream;
            IPersistStream persistStream = new SimpleLineSymbolClass();
            persistStream.Load(memoryBlobStream);
            return persistStream as ISimpleLineSymbol;
        }
保存符号的函数没有问题,但读取符号的函数在persistStream.Load(memoryBlobStream)这一行熄了火,百度谷歌必应劳而无功后,愤怒的写下如下代码,本以为不可能有问题:
IPersistStream persistStream = symbol as IPersistStream;
IMemoryBlobStream memoryBlobStream = new MemoryBlobStreamClass();
persistStream.Save(memoryBlobStream, 0);
IPersistStream persistStream2 = new SimpleLineSymbolClass();
persistStream2.Load(memoryBlobStream);
但还是在Load处卡壳,让人怀疑IPersistStream的能力,不过如果采用以下狗血的方式,则能通过
IPersistStream persistStream = symbol as IPersistStream;
IMemoryBlobStream memoryBlobStream = new MemoryBlobStreamClass();
persistStream.Save(memoryBlobStream, 0);
memoryBlobStream.SaveToFile("D:\\Symbol.blb");
memoryBlobStream.LoadFromFile("D:\\Symbol.blb");

IPersistStream persistStream2 = new SimpleLineSymbolClass();
persistStream2.Load(memoryBlobStream);
什么原因至今未弄明白,想在字段中保存的Symbol的想法也被文件式保存取代,以上困惑,还请高手指教。
前面是旧事重提了,今天又遇到类似的问题,所不同的是想在要素的字段中保存一个Element,真是作孽。由于时间久远,又在老路上浪费不少生命,无奈之下,再度求助DevelopHelp,发现还有一个IMemoryBlobStreamVariant接口未用,并且惊喜的发现这个接口有一个将MemoryBlob输出为Byte[]数组的方法,想到Byte[]数组可以与String相互转换,计上心来。Blob类型没必要用了,直接建一个普通的String类型字段就可以拿来保存Element了,当然这个字段的长度一定要设的足够大,最好用String字段长度的最大值2147483647,因为天知道一个Element对象转换得来的字符串有多长,还是小心谨慎的好。这样一试,竟然圆满了,喜出望外啊,第一时间跑到坛子上来分享。
        public void SaveElementToField(IFeature feature, string field, IMarkerElement element)
        {
            IMemoryBlobStream pMemoryBlobStream = new MemoryBlobStreamClass();
            IPersistStream pPersistStream = element as IPersistStream;
            pPersistStream.Save(pMemoryBlobStream, 0);
            IMemoryBlobStreamVariant mbv = pMemoryBlobStream as IMemoryBlobStreamVariant;
            object obj;
            mbv.ExportToVariant(out obj);
            byte[] bobj = (byte[])obj;
            string str = Convert.ToBase64String(bobj);
            int index = feature.Fields.FindField(field);
            feature.set_Value(index, str);
            feature.Store();
        }
        public IMarkerElement ReadElementFromField(IFeature feature, string field)
        {
            int index = feature.Fields.FindField(field);
            string str = feature.get_Value(index).ToString();
            byte[] bobj = Convert.FromBase64String(str);
            IMemoryBlobStream pMemoryBlobStream = new MemoryBlobStreamClass();
            IMemoryBlobStreamVariant mbv = pMemoryBlobStream as IMemoryBlobStreamVariant;
            mbv.ImportFromVariant((object)bobj);
            IPersistStream pPersistStream = new MarkerElementClass();
            pPersistStream.Load(pMemoryBlobStream);
            return pPersistStream as IMarkerElement;
        }
 

        /// <summary>
        /// 序列化(将对象序列化成xml文件)
        /// </summary>
        /// <param name="xmlfile">序列化文件路径</param>
        /// <param name="obj">序列化对象</param>
        /// <returns></returns>
        public static bool xmlSerializer(string xmlfile,object obj)
        {
            try
            {
                //判断是否支持IPersistStream接口,只有支持该接口的对象才能进行序列化
                if (obj is ESRI.ArcGIS.esriSystem.IPersistStream)
                {
                    ESRI.ArcGIS.esriSystem.IPersistStream pStream = obj as ESRI.ArcGIS.esriSystem.IPersistStream;

                    ESRI.ArcGIS.esriSystem.IXMLStream xmlStream = new ESRI.ArcGIS.esriSystem.XMLStreamClass();

                    pStream.Save(xmlStream as ESRI.ArcGIS.esriSystem.IStream, 0);

                    xmlStream.SaveToFile(xmlfile);

                    return true;
                }
                return false;
            }
            catch (System.Exception e)
            {
                return false;
            }           
        }



--------------------------------------------------------------------------------


        /// <summary>
        /// 反序列化(将xml反序列化成指定的对象)
        /// </summary>
        /// <param name="xmlPathFile">序列化文件</param>
        /// <param name="obj">序列化对象</param>
        /// <returns></returns>
        public static bool XmlDeSerializer(string xmlPathFile,ref object obj)        
        {    
            try
            {
                //判断文件是否存在
                if (System.IO.File.Exists(xmlPathFile) && System.IO.Path.GetExtension(xmlPathFile) == ".xml")
                {
                    ESRI.ArcGIS.esriSystem.IPersistStream pStream = obj as ESRI.ArcGIS.esriSystem.IPersistStream;

                    ESRI.ArcGIS.esriSystem.IXMLStream xmlStream = new ESRI.ArcGIS.esriSystem.XMLStreamClass();

                    xmlStream.LoadFromFile(xmlPathFile);
                    pStream.Load(xmlStream as ESRI.ArcGIS.esriSystem.IStream);

                    return true;
                }
                return false;
            }
            catch(Exception ex)
            {
                return false;
            }
        }  

 

posted on 2013-01-21 16:54  bobird  阅读(635)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3