ArcEngine 数据导出Shape的几种方式

原文链接:https://blog.csdn.net/whz1571443359/article/details/79619752

方法一

​ 创建一个shape要素类,结果与导出要素类一致,保存使用store速度最慢,忽略


方法二

​ 使用IFeatureBuffer速度较快,缺点:数据量大,导出的时候容易报内存损坏错误使程序崩溃

private static void ExportShapeLayer(string filePath, IFeatureLayer featureLayer)
{

    string parentPath = filePath.Substring(0, filePath.LastIndexOf('\\'));
    string fcName = filePath.Substring(filePath.LastIndexOf('\\') + 1, filePath.Length - filePath.LastIndexOf('\\') - 1);
    string filedir = parentPath.Substring(parentPath.LastIndexOf('\\') + 1, parentPath.Length - parentPath.LastIndexOf('\\') - 1);
    DirectoryInfo directoryInfoPath = Directory.GetParent(parentPath);
    IWorkspaceFactory pWorkSpaceFac = new ShapefileWorkspaceFactoryClass();
    IFeatureWorkspace pFeatureWorkSpace = pWorkSpaceFac.OpenFromFile(parentPath, 0) as IFeatureWorkspace;

    //创建字段集2
    IFeatureClassDescription fcDescription = new FeatureClassDescriptionClass();
    IObjectClassDescription ocDescription = (IObjectClassDescription)fcDescription;//创建必要字段
    IFields fields = ocDescription.RequiredFields;
    int shapeFieldIndex = fields.FindField(fcDescription.ShapeFieldName);
    IField field = fields.Field[shapeFieldIndex];
    IGeometryDef geometryDef = field.GeometryDef;
    IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;

    if (featureLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
        geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;

    else if (featureLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
        geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolyline;

    else if (featureLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPoint)
        geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;

    IProjectedCoordinateSystem tProjectedCoordinateSystem = (featureLayer as IGeoDataset).SpatialReference as IProjectedCoordinateSystem;
    geometryDefEdit.SpatialReference_2 = tProjectedCoordinateSystem;

    IFieldChecker fieldChecker = new FieldCheckerClass();
    IEnumFieldError enumFieldError = null;
    IFields validatedFields = null; //将传入字段 转成 validatedFields
    fieldChecker.ValidateWorkspace = (IWorkspace)pFeatureWorkSpace;
    fieldChecker.Validate(fields, out enumFieldError, out validatedFields);
    IFeatureClass shpFeatureClass = pFeatureWorkSpace.CreateFeatureClass(fcName, validatedFields, ocDescription.InstanceCLSID, ocDescription.ClassExtensionCLSID, esriFeatureType.esriFTSimple, fcDescription.ShapeFieldName, "");

    for (int i = 0; i < featureLayer.FeatureClass.Fields.FieldCount; i++)
    {

        IField tfield = featureLayer.FeatureClass.Fields.get_Field(i);
        if (tfield.Type == esriFieldType.esriFieldTypeBlob) continue;
        if (filterArr.Contains(tfield.Name)) continue;
        shpFeatureClass.AddField(tfield);
    }

    IFeatureLayer shpfeatureLayer = new FeatureLayerClass();
    shpfeatureLayer.FeatureClass = shpFeatureClass;

    ITable tb = featureLayer.FeatureClass as ITable;
    IQueryFilter tQueryFilter = new QueryFilterClass();
    tQueryFilter.WhereClause = "";
    tQueryFilter.AddField(featureLayer.FeatureClass.OIDFieldName);

    //计算要素总数

    int totalCount = tb.RowCount(tQueryFilter);

    ImportFeatureClassData_MarshalReleaseComObject(featureLayer, shpfeatureLayer, totalCount);

}

public static void ImportFeatureClassData_MarshalReleaseComObject(IFeatureLayer featureLayer, IFeatureLayer shpFeatureLayer, int totalCount)
{

    try
    {

        int i = 0;

        IFeatureClass shpFeatureClass = shpFeatureLayer.FeatureClass;
        IFeatureBuffer pFeatureBuffer = shpFeatureClass.CreateFeatureBuffer();
        IFeatureCursor pFeatureCursor = shpFeatureClass.Insert(true);
        IFeatureCursor pFeatureCursorSource = featureLayer.FeatureClass.Search(null, false);
        IFeature pFeatureSource = pFeatureCursorSource.NextFeature();
        while (pFeatureSource != null)
        {

            i++;
            ZzCom.CommonUtil.SimpleWaiterHelper.SetValue(i);

            if (pFeatureSource.ShapeCopy == null)
            {
                pFeatureSource = pFeatureCursorSource.NextFeature();
                continue;
            }

            IFeature pFeatureTarget = pFeatureBuffer as IFeature;
            ArcengineUtil.SetZValue(pFeatureTarget, pFeatureSource.ShapeCopy);
            //修复几何,否则质检容易报自相交错误
            IGeometry geometry = GeometryOperateHelper.SimplifyGeometry(pFeatureSource.ShapeCopy);

            ArcengineUtil.SetZValue(pFeatureTarget, geometry);
            pFeatureTarget.Shape = geometry;

            IFields fields = FeatureOperatorUtil.CopyFields(pFeatureSource.Fields);

            IFields tagerfields = FeatureOperatorUtil.CopyFields(pFeatureTarget.Fields);
            Dictionary<int, int> tempdic = FeatureOperatorUtil.GetFieldMap(fields, tagerfields);
            FeatureOperatorUtil.CopyFeatureAttribute(pFeatureSource, pFeatureTarget, tempdic);

            //这里容易报内存损坏,继续执行会重复插入该记录造成记录有重复(原因:可能是频繁的读写)

            pFeatureCursor.InsertFeature(pFeatureBuffer);

            if (i % 500 == 0)
            {
                pFeatureCursor.Flush();

                Marshal.FinalReleaseComObject(pFeatureTarget);
                Marshal.FinalReleaseComObject(pFeatureSource);
                Marshal.FinalReleaseComObject(pFeatureBuffer);
                Marshal.FinalReleaseComObject(pFeatureCursor);
                GC.Collect(); // 强制对所有代进行垃圾回收。
                GC.WaitForPendingFinalizers(); //挂起当前线程,直到处理终结器队列的线程清空该队列为止。
                pFeatureBuffer = shpFeatureClass.CreateFeatureBuffer();
                pFeatureCursor = shpFeatureClass.Insert(true);
                pFeatureTarget = pFeatureBuffer as IFeature;

            }

            pFeatureSource = pFeatureCursorSource.NextFeature();

        }

        pFeatureCursor.Flush();
        Marshal.FinalReleaseComObject(pFeatureCursor);
        if (pFeatureBuffer != null)
            Marshal.FinalReleaseComObject(pFeatureBuffer);
        Marshal.FinalReleaseComObject(pFeatureCursorSource);

        //释放
        GC.Collect();
        GC.WaitForPendingFinalizers();

        ZzCom.CommonUtil.SimpleWaiterHelper.SetValue(totalCount);
        MediaTypeNames.Application.DoEvents();
    }

    catch (Exception e)
    {
        ZzLog4net.ZzLogUtil.Logger.LogInfo(string.Format("异常信息:{0} 异常位置:{1} 时间:'{2}'", e.Message, e,
                                                         DateTime.Now));
        throw e;
    }

    finally
    {
    }
}

方法三

​ 使用IFeatureDataConverter2或者IFeatureDataConverter,速度最快,缺点无法知道导出的要素总数和当前要素,无法做进度条,不知道arcgis使用的那种方法(求告知),速度快还有进度条,这个地方要注意把大字段处理了,处理方案可以把输出字段集拷贝一份,把大字段改成string类型,或者使用IFeatureDataConverter2像以下处理。

public static void ExportFeatureClassToShp(IFeatureLayer featureLayer, string exportShapeFileName, string exportFilePath, string exportShapeType)
{

    try
    {
        IFeatureClass apFeatureClass = featureLayer.FeatureClass;
        if (apFeatureClass == null)    return;
        if (exportShapeFileName == "") return;

        //设置导出要素类的参数
        IFeatureClassName pOutFeatureClassName = new FeatureClassNameClass();
        IDataset pOutDataset = (IDataset)apFeatureClass;

        pOutFeatureClassName = (IFeatureClassName)pOutDataset.FullName;
        //IWorkspaceFactory pShpWorkspaceFactory = new ShapefileWorkspaceFactoryClass();
        //IWorkspaceName pInWorkspaceName = new WorkspaceNameClass();
        //pInWorkspaceName = pShpWorkspaceFactory.Create(ExportFilePath, ExportShapeFileName, null, 0);

        IWorkspaceFactory pWorkSpaceFac = new ShapefileWorkspaceFactoryClass();
        IWorkspace workspace = pWorkSpaceFac.OpenFromFile(exportFilePath, 0);
        IFeatureDatasetName pInFeatureDatasetName = null;

        IDataset outDataSet = workspace as IDataset;
        IWorkspaceName outWorkspaceName = outDataSet.FullName as IWorkspaceName;
        IFeatureClassName pInFeatureClassName = new FeatureClassNameClass();
        IDatasetName pInDatasetClassName;
        pInDatasetClassName = (IDatasetName)pInFeatureClassName;
        pInDatasetClassName.Name = exportShapeFileName;//作为输出参数
        pInDatasetClassName.WorkspaceName = outWorkspaceName;
        long iCounter;
        IFields pOutFields, pInFields;
        IFieldChecker pFieldChecker;
        IField pGeoField;
        IEnumFieldError pEnumFieldError = null;
        pInFields = apFeatureClass.Fields;
        pFieldChecker = new FieldChecker();
        pFieldChecker.InputWorkspace = apFeatureClass.FeatureDataset.Workspace;
        pFieldChecker.ValidateWorkspace = workspace;
        pFieldChecker.Validate(pInFields, out pEnumFieldError, out pOutFields);

        pGeoField = null;

        for (iCounter = 0; iCounter < pOutFields.FieldCount; iCounter++)
        {
            if (pOutFields.Field[(int) iCounter].Type != esriFieldType.esriFieldTypeGeometry) 
                continue;
            pGeoField = pOutFields.Field[(int)iCounter];
            break;

        }

        List<int> FieldErrorList = new List<int>();
        IFieldError fieldError = pEnumFieldError.Next();

        while (fieldError != null)
        {

            FieldErrorList.Add(fieldError.FieldIndex);
            fieldError = pEnumFieldError.Next();

        }

        IQueryFilter inputQueryFilter = null;
        ISelectionSet pSelectionSet = null;

        if (exportShapeType.Equals("所有要素"))
            inputQueryFilter = new QueryFilterClass {WhereClause = ""};

        else if (exportShapeType.Equals("所选要素"))
        {
            inputQueryFilter = new QueryFilterClass
            {
                WhereClause = ""
            };
            IFeatureSelection pFeatureSelection = featureLayer as IFeatureSelection;
            //pFeatureSelection.SelectFeatures(InputQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
            pSelectionSet = pFeatureSelection.SelectionSet;

        }

        else if (exportShapeType.Equals("视图范围内所有要素"))
        {

            IEnvelope env = EsriCtrlUtil.MapCtrl.Extent;
            IGeometry geometry = env;
            ISpatialFilter spatialFilter = new SpatialFilterClass();
            spatialFilter.Geometry = geometry;
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

            inputQueryFilter = spatialFilter;

            inputQueryFilter.WhereClause = "";

        }
        StringBuilder strBuilderSubFields = new StringBuilder();

        string subFields = "";

        IFields pFields = new FieldsClass();

        IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields;

        for (int i = 0; i < pOutFields.FieldCount; i++)
        {

            IField pField = pOutFields.get_Field(i);

            if (pField.Type == esriFieldType.esriFieldTypeBlob ||
                pField.Type == esriFieldType.esriFieldTypeRaster ||
                pField.Type == esriFieldType.esriFieldTypeGUID) continue;

            if (FieldErrorList.Contains(i))
                continue;

            pFieldsEdit.AddField(pField);

            if (inputQueryFilter != null) 
                inputQueryFilter.AddField(pField.Name);
            strBuilderSubFields.Append(pField.Name + ",");

        }

        string SubFields = strBuilderSubFields.ToString().Substring(0, strBuilderSubFields.Length - 1);

        if (inputQueryFilter != null) 
            inputQueryFilter.SubFields = SubFields;

        IGeometryDef pOutGeometryDef;
        IGeometryDefEdit pOutGeometryDefEdit;
        pOutGeometryDef = pGeoField.GeometryDef;
        pOutGeometryDefEdit = (IGeometryDefEdit)pOutGeometryDef;
        pOutGeometryDefEdit.GridCount_2 = 1;
        pOutGeometryDefEdit.set_GridSize(0, 1500000);
        int strSubIndex = pOutDataset.Name.IndexOf('.');
        string fcName = pOutDataset.Name.Substring(strSubIndex + 1, pOutDataset.Name.Length - (strSubIndex + 1));
        IFeatureClassName sourceFeatureClassName = new FeatureClassNameClass();
        sourceFeatureClassName = (IFeatureClassName)pOutDataset.FullName;
        IDatasetName sourceDatasetName = (IDatasetName)sourceFeatureClassName;
        IFeatureDataConverter2 pShpToClsConverter2 = new FeatureDataConverterClass();
        pShpToClsConverter2.ConvertFeatureClass(sourceDatasetName, inputQueryFilter, pSelectionSet, null, pInFeatureClassName, pOutGeometryDef, pOutFields, "", 1000, 0);

    }

    catch (Exception ex)
    {
        throw ex;
    }
}
上一篇:ArcEngine打开GDB,SHP的方法


下一篇:C#+arcengine获得栅格数据的属性表