在对GDB格式的矢量数据库进行检查时,经常需要将检查结果导出为shp文件,或者GDB格式文件;形成了两个小的处理思路,在这里总结分享。
1 导出GDB文件
介绍了两种方法,主要针对要导出的数据格式为GDB类型的输出文件;两种思路的差异是:
- 前者将整个GDB以文件形式拷贝,然后在删除不需要的图层;
- 后者新建GDB文件,然后只拷贝需要的要素类
1.1 整体拷贝+图层删除思路
该思路将整个GDB文件视为一个目录,直接拷贝到结果目录中,然后再删除多余图层的方法
1.1.1 GDB文件整体拷贝
之前博文C#编程学习13:文件及文件夹检索与拷贝已经对文件夹拷贝的代码进行了总结
//需要引用System.IO命名空间,实现代码如下: private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting) { bool ret = false; try { if (Directory.Exists(SourcePath)) { //不存在则创建 if (Directory.Exists(DestinationPath) == false) Directory.CreateDirectory(DestinationPath); foreach (string fls in Directory.GetFiles(SourcePath)) { FileInfo flinfo = new FileInfo(fls); flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting); } foreach (string drs in Directory.GetDirectories(SourcePath)) { DirectoryInfo drinfo = new DirectoryInfo(drs); if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false) ret = false; } } ret = true; } catch (Exception ex) { ret = false; } return ret; } //使用方法: bool copy = CopyDirectory("c:\\src.gdb", "c:\\temp\\dst.gdb", true);
1.1.2 删除多余图层
之前博文:基于C#的ArcEngine二次开发40:如何删除临时GDB文件;对此做过分析
public void DeleteFeatureClass(IWorkspace workspace, string featueClassName) { //根据名称删除数据库要素 IFeatureWorkspaceManage featureWorkspaceMange = (workspace as IFeatureWorkspace) as IFeatureWorkspaceManage; IEnumDatasetName enumDatasetName = workspace.get_DatasetNames(esriDatasetType.esriDTFeatureClass); IDatasetName datasetName = enumDatasetName.Next(); while (datasetName != null) { if (datasetName.Name.Equals(featueClassName)) { featureWorkspaceMange.DeleteByName(datasetName);//删除指定要素类 break; } datasetName = enumDatasetName.Next(); } }
1.1.3 拷贝检查
检查LRDL的name是否为空的示例
private void checkOutput(string srcGDB, string dstGDB) { //1. GDB拷贝 if(!System.IO.Exists(dstGDB)) { CopyDirectory(srcGDB, dstGDB); } //2. 打开文件 IWorkspaceFactory worFact =new FileGDBWorkspaceFactory(); IWorkspace workspace = worFact.OpenFromFile(dstGDB, 0); //3. 假定移除AANP层 DeleteFeatureClass("AANP"); //4. 假设检查LRDL,需要增加字段进行错误信息记录 IFeatureClass poFeaterClass = ofeatureWorkspace.OpenFeatureClass("LRDL"); int checkFieldIndex = poFeaterClass.FindField("检查结果记录"); if(checkFieldIndex == -1) { IFields pFields = new FieldClass(); IFieldEdit pFieldEdit = pFields as IFieldEdit; pFieldEdit.Name_2 = "检查结果记录"; pFieldEdit.Type_2 = filedType; pFieldEdit.Length_2 = fieldLength; pTable.AddField(pFieldEdit); } checkFieldIndex = poFeaterClass.FindField("检查结果记录"); //5. 遍历每个要素进行检查 IFeatureCursor pCursor = poFeaterClass.Update(null, false); IFeature pFeature = pCursor.NextFeature(); while(pFeature != null) { int nameIndex = pFeature.get_Field("RNN"); string name = pFeature.get_Value(nameIndex).ToString().Trim(); if(name == "") { pFeature.get_Value(checkFieldIndex, "名称为空,错误") pCursor.UpdateFeature(); } else { pCursor.DeleteFeature(); } pFeature = pCursor.NextFeature(); } //6. 注销对象 Marshal.FinalReleaseComObject(pCursor); Marshal.FinalReleaseComObject(poFeaterClass); Marshal.FinalReleaseComObject(workspace); GC.Collect(); }
1.2 创建GDB+ConvertFeatureClass
1.2.1 创建GDB文件
该内容见系列文章:
使用GP工具创建:
//gdbFolder: 设置存放将要创建GDB文件的目录 //gdbFileName: 设置GDB文件的名称 public void createGDBFile(string gdbFolder, string gdbFileName) { //创建gp工具 ESRI.ArcGIS.Geoprocessor.Geoprocessor pGeoprocessor = ESRI.ArcGIS.Geoprocessor.Geoprocessor{}; pGeoprocessor.OverwriteOutput = true; pGeoprocessor.AddOutputToMap = false; //创建GDB文件 CreateFileGDB processor = new CreateFileGDB {}; processor.out_folder_path = gdbFolder; processor.out_name = gdbFileName; pGeoprocessor.Execute(processor, null); }
1.2.2 ConvertFeatureClass
此部分参见之前的文章:基于C#的ArcEngine二次开发29:GDB文件操作及异常处理
public void CopyLayerFromGDB(string inPath, string gdbLayerName, string ouPath, string ouGdbLayerName) { //1. 指定输入要素 IWorkspaceFactory workspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass(); IWorkspace iworkspace = iworkspaceFactory.OpenFromFile(inPath, 0); IFeatureWorkspace ifeatureWorkspace = (IFeatureWorkspace)iworkspace; IFeatureClass ipFeaterClass = ifeatureWorkspace.OpenFeatureClass(checkLayerName); //2. 设置输入图层名 IWorkspaceName inWorkspaceName = (inWorkspace as IDataset).FullName as IWorkspaceName ; IFeatureClassName inFeatureClassName = new FeatureClassNameClass(); IDatasetName inDatasetName = (IDatasetName)inFeatureClassName; inDatasetName.WorkspaceName = inWorkspaceName; inDatasetName.Name = gdbLayerName; //3. 在目标GDB中创建导出图层 IWorkspaceFactory oworkspaceFactory = new AccessWorkspaceFactory(); IWorkspace oworkspace = oworkspaceFactory.OpenFromFile(ouPath, 0); IFeatureWorkspace ofeatureWorkspace = (IFeatureWorkspace)workspace; IFeatureClass poFeaterClass = ofeatureWorkspace.OpenFeatureClass(mdbLayerName); IWorkspace2 oworkspace2 = (IWorkspace2)oworkspace; if (oworkspace2.get_NameExists(esriDatasetType.esriDTFeatureClass, checkLayerName)) { IFeatureClass pFC = ofeatureWorkspace.OpenFeatureClass(checkLayerName); IDataset pDS = pFC as IDataset; pDS.Delete(); } //4. 创建输出要素类 IWorkspaceName ouWorkspaceName = (ouWorkspace as IDataset).FullName as IWorkspaceName ; IFeatureClassName ouFeatureClassName = new FeatureClassNameClass(); IDatasetName ouDatasetName = (IDatasetName)ouFeatureClassName; ouDatasetName.WorkspaceName = ouWorkspaceName; ouDatasetName.Name = ouGdbLayerName; //5. 字段赋值 IFieldChecker fieldChecker = new FieldCheckerClass(); fieldChecker.InputWorkspace = iworkspace;//输入数据集工作空间 fieldChecker.ValidateWorkspace = ouWorkpace;//输出工作空间 IFields outFeatureClassFields; IEnumFieldError enumFieldError; fieldChecker.Validate(inFeatureClassFields, out enumFieldError, out outFeatureClassFields); //6. 几何定义 IField geometryField = outFeatureClassFields.get_Field(outFeatureClassFields.FindField(inFeatureClass.ShapeFieldName)); IGeometryDef geometryDef = geometryField.GeometryDef; //7. 查询语句 -- 如果还要进行上述的LRDL层的空值监测,直接写到sql语句中就可以了 QueryFilter qf = new QueryFilterClass(); qf.WhereClause = ""; //8. 调用转换函数 IFeatureDataConverter fctofc = new FeatureDataConverterClass(); IEnumInvalidObject enumErrors = fctofc.ConvertFeatureClass(inFeatureClassName, qf, null, outFeatureClassName, geometryDef, outFeatureClassFields, "", 1000, 0); }
调用与第一种类似,打开拷贝出的GDB文件的兴趣图层,然后直接进行处理就行了
2 导出shp文件(以点要素为例)
这个函数是针对对数据进行处理后,结果以数据点的形式存储在shp中,自定义属性字段并输出要素
/// <summary> /// 将点集导出为shp文件 /// </summary> /// <param name="inPath">输入数据集</param> /// <param name="liPts">要导出的点集</param> /// <param name="checkLayerName">点集的来源图层</param> /// <param name="ouPath">导出的shape文件的结果保存路径</param> public void ExportPtsToShapefile(string inPath, List<IPoint> liPts, string checkLayerName, string ouPath) { //1. 打开工作空间 string strShapeFolder = System.IO.Path.GetDirectoryName(ouPath); const string strShapeFieldName = "shape"; IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass(); IFeatureWorkspace pWS = (IFeatureWorkspace)pWSF.OpenFromFile(strShapeFolder,0); //2. 设置字段集 IFields pFields = new FieldsClass(); IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields; //3. 设置字段 IField pField = new FieldClass(); IFieldEdit pFieldEdit = (IFieldEdit)pField; //4. 创建类型为几何类型的字段 pFieldEdit.Name_2 = strShapeFieldName; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry; //为esriFieldTypeGeometry类型的字段创建几何定义,包括类型和空间参照 IGeometryDef pGeoDef = new GeometryDefClass(); //The geometry definition for the field if IsGeometry is TRUE. IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef; //4.1 将原始数据的投影信息赋值给新的检查结果图层 IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory(); IWorkspace workspace = workspaceFactory.OpenFromFile(inPath, 0); IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace; IFeatureClass pFeaterClass = featureWorkspace.OpenFeatureClass(checkLayerName);//这个地方可以继续研究如何更简便的获取工作空间的坐标系统 IGeoDataset geoDatabase = pFeaterClass as IGeoDataset; //设置坐标系统 IProjectedCoordinateSystem tProjectedCoordinateSystem = geoDatabase.SpatialReference as IProjectedCoordinateSystem; pGeoDefEdit.SpatialReference_2 = tProjectedCoordinateSystem; pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint; pFieldEdit.GeometryDef_2 = pGeoDef; pFieldsEdit.AddField(pField); //添加其他的字段 pField = new FieldClass(); pFieldEdit = (IFieldEdit)pField; pFieldEdit.Name_2 = "X"; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble; //pFieldEdit.Precision_2 = 7;//数值精度 //pFieldEdit.Scale_2 = 6;//小数点位数 pFieldsEdit.AddField(pField); pField = new FieldClass(); pFieldEdit = (IFieldEdit)pField; pFieldEdit.Name_2 = "Y"; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble; //pFieldEdit.Precision_2 = 7;//数值精度 //pFieldEdit.Scale_2 = 6;//小数点位数 pFieldsEdit.AddField(pField); //创建shapefile string strShapeName = System.IO.Path.GetFileName(ouPath); IFeatureClass shpFeatureClass = pWS.CreateFeatureClass(strShapeName, pFields, null, null, esriFeatureType.esriFTSimple, strShapeFieldName, ""); //5. 向shape中添加要素 IPoint pPoint = new PointClass(); foreach (IPoint pt in liPts) { IFeature pFeature = shpFeatureClass.CreateFeature(); //5.1 将点坐标设置到属性表中 //获取字段,并对字段值进行属性赋值 IFields fields = pFeature.Fields;//获取该对象的字段 int xIdx = fields.FindFieldByAliasName("X"); pFeature.set_Value(xIdx, pt.X); int yIdx = fields.FindFieldByAliasName("Y"); pFeature.set_Value(yIdx, pt.Y); //5.2 将点设置为shp文件的图形要素 pFeature.Shape = pt;//这一句十分重要,不然点显示不出来 //如果导出的其他类型的元素(IPolygon,IPolyline) pFeature.Store(); } }