Exporting Data to Shapefile in ArcEngine

Creating a shapefile feature class with Store method yields identical results to exporting feature classes, but performs significantly slower due to storage operations.

Method 2: IFeatureBuffer Approach

Using IFeatureBuffer provides faster performance but carries memory corruption risks with large datasets that can crash appliactions.


private static void ExportToShapefile(string outputPath, IFeatureLayer sourceLayer)
{
    string directory = Path.GetDirectoryName(outputPath);
    string fileName = Path.GetFileName(outputPath);
    
    IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactoryClass();
    IFeatureWorkspace featureWorkspace = workspaceFactory.OpenFromFile(directory, 0) as IFeatureWorkspace;
    
    IFeatureClassDescription classDesc = new FeatureClassDescriptionClass();
    IObjectClassDescription objDesc = (IObjectClassDescription)classDesc;
    IFields baseFields = objDesc.RequiredFields;
    
    int geometryFieldIndex = baseFields.FindField(classDesc.ShapeFieldName);
    IField geometryField = baseFields.get_Field(geometryFieldIndex);
    IGeometryDef geometryDefinition = geometryField.GeometryDef;
    IGeometryDefEdit geometryEditor = (IGeometryDefEdit)geometryDefinition;
    
    switch(sourceLayer.FeatureClass.ShapeType)
    {
        case esriGeometryType.esriGeometryPolygon:
            geometryEditor.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
            break;
        case esriGeometryType.esriGeometryPolyline:
            geometryEditor.GeometryType_2 = esriGeometryType.esriGeometryPolyline;
            break;
        case esriGeometryType.esriGeometryPoint:
            geometryEditor.GeometryType_2 = esriGeometryType.esriGeometryPoint;
            break;
    }
    
    IProjectedCoordinateSystem spatialRef = (sourceLayer as IGeoDataset).SpatialReference as IProjectedCoordinateSystem;
    geometryEditor.SpatialReference_2 = spatialRef;
    
    IFieldChecker fieldValidator = new FieldCheckerClass();
    IEnumFieldError fieldErrors = null;
    IFields validatedFields = null;
    fieldValidator.ValidateWorkspace = (IWorkspace)featureWorkspace;
    fieldValidator.Validate(baseFields, out fieldErrors, out validatedFields);
    
    IFeatureClass outputFeatureClass = featureWorkspace.CreateFeatureClass(fileName, validatedFields, 
        objDesc.InstanceCLSID, objDesc.ClassExtensionCLSID, esriFeatureType.esriFTSimple, 
        classDesc.ShapeFieldName, "");
        
    for(int i = 0; i < sourceLayer.FeatureClass.Fields.FieldCount; i++)
    {
        IField currentField = sourceLayer.FeatureClass.Fields.get_Field(i);
        if(currentField.Type == esriFieldType.esriFieldTypeBlob) continue;
        outputFeatureClass.AddField(currentField);
    }
    
    IFeatureLayer outputLayer = new FeatureLayerClass();
    outputLayer.FeatureClass = outputFeatureClass;
    
    ITable sourceTable = sourceLayer.FeatureClass as ITable;
    IQueryFilter queryFilter = new QueryFilterClass();
    queryFilter.WhereClause = "";
    queryFilter.AddField(sourceLayer.FeatureClass.OIDFieldName);
    
    int featureCount = sourceTable.RowCount(queryFilter);
    TransferFeaturesWithBuffer(sourceLayer, outputLayer, featureCount);
}

private static void TransferFeaturesWithBuffer(IFeatureLayer sourceLayer, IFeatureLayer targetLayer, int totalFeatures)
{
    try
    {
        int processedCount = 0;
        IFeatureClass targetClass = targetLayer.FeatureClass;
        IFeatureBuffer featureBuffer = targetClass.CreateFeatureBuffer();
        IFeatureCursor insertCursor = targetClass.Insert(true);
        IFeatureCursor sourceCursor = sourceLayer.FeatureClass.Search(null, false);
        IFeature sourceFeature = sourceCursor.NextFeature();
        
        while(sourceFeature != null)
        {
            processedCount++;
            
            if(sourceFeature.ShapeCopy == null)
            {
                sourceFeature = sourceCursor.NextFeature();
                continue;
            }
            
            IFeature targetFeature = featureBuffer as IFeature;
            IGeometry processedGeometry = GeometryProcessor.SimplifyGeometry(sourceFeature.ShapeCopy);
            targetFeature.Shape = processedGeometry;
            
            IFields sourceFields = FieldManager.CopyFields(sourceFeature.Fields);
            IFields targetFields = FieldManager.CopyFields(targetFeature.Fields);
            Dictionary<int int=""> fieldMapping = FieldManager.CreateFieldMapping(sourceFields, targetFields);
            FieldManager.CopyAttributes(sourceFeature, targetFeature, fieldMapping);
            
            insertCursor.InsertFeature(featureBuffer);
            
            if(processedCount % 500 == 0)
            {
                insertCursor.Flush();
                ReleaseComObjects(targetFeature, sourceFeature, featureBuffer, insertCursor);
                GC.Collect();
                GC.WaitForPendingFinalizers();
                
                featureBuffer = targetClass.CreateFeatureBuffer();
                insertCursor = targetClass.Insert(true);
                targetFeature = featureBuffer as IFeature;
            }
            
            sourceFeature = sourceCursor.NextFeature();
        }
        
        insertCursor.Flush();
        ReleaseComObjects(insertCursor, featureBuffer, sourceCursor);
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
    catch(Exception ex)
    {
        throw ex;
    }
}
</int>

Method 3: IFeatureDataConverter Approach

IFeatureDataConverter2 or IFeatureDataConverter offers the fastest performance but lacks progress tracking capabilities. Large field types require special handling.


public static void ConvertToShapefile(IFeatureLayer inputLayer, string outputName, string outputPath)
{
    try
    {
        IFeatureClass sourceClass = inputLayer.FeatureClass;
        if(sourceClass == null || string.IsNullOrEmpty(outputName)) return;
        
        IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactoryClass();
        IWorkspace outputWorkspace = workspaceFactory.OpenFromFile(outputPath, 0);
        
        IFeatureClassName outputClassName = new FeatureClassNameClass();
        IDatasetName outputDatasetName = (IDatasetName)outputClassName;
        outputDatasetName.Name = outputName;
        
        IDataset workspaceDataset = outputWorkspace as IDataset;
        outputDatasetName.WorkspaceName = workspaceDataset.FullName as IWorkspaceName;
        
        IFieldChecker fieldChecker = new FieldCheckerClass();
        fieldChecker.InputWorkspace = sourceClass.FeatureDataset.Workspace;
        fieldChecker.ValidateWorkspace = outputWorkspace;
        
        IFields inputFields = sourceClass.Fields;
        IFields outputFields;
        IEnumFieldError fieldErrors = null;
        fieldChecker.Validate(inputFields, out fieldErrors, out outputFields);
        
        List<int> invalidFields = new List<int>();
        IFieldError fieldError = fieldErrors.Next();
        while(fieldError != null)
        {
            invalidFields.Add(fieldError.FieldIndex);
            fieldError = fieldErrors.Next();
        }
        
        IQueryFilter filter = new QueryFilterClass { WhereClause = "" };
        StringBuilder fieldList = new StringBuilder();
        IFields filteredFields = new FieldsClass();
        IFieldsEdit fieldsEditor = (IFieldsEdit)filteredFields;
        
        for(int i = 0; i < outputFields.FieldCount; i++)
        {
            IField currentField = outputFields.get_Field(i);
            if(currentField.Type == esriFieldType.esriFieldTypeBlob || 
               currentField.Type == esriFieldType.esriFieldTypeRaster ||
               currentField.Type == esriFieldType.esriFieldTypeGUID) continue;
               
            if(invalidFields.Contains(i)) continue;
            
            fieldsEditor.AddField(currentField);
            filter.AddField(currentField.Name);
            fieldList.Append(currentField.Name + ",");
        }
        
        string subFields = fieldList.ToString().TrimEnd(',');
        filter.SubFields = subFields;
        
        IDataset sourceDataset = sourceClass as IDataset;
        IFeatureClassName sourceClassName = (IFeatureClassName)sourceDataset.FullName;
        IDatasetName sourceDatasetName = (IDatasetName)sourceClassName;
        
        IFeatureDataConverter2 converter = new FeatureDataConverterClass();
        converter.ConvertFeatureClass(sourceDatasetName, filter, null, null, outputClassName, 
            null, filteredFields, "", 1000, 0);
    }
    catch(Exception ex)
    {
        throw ex;
    }
}
</int></int>

Method 4: Geoprocesisng Tool Approach

Using the FeatureClassToShapefile geoprocessing tool provides a straightforward solution with built-in error handling.


private void ExecuteShapefileConversion(string databaseName, string connectionFile, string outputFolder)
{
    string sdeConnection = @"E:\connections\ConnectionTo" + databaseName + ".sde";
    
    IWorkspace sdeWorkspace = DatabaseManager.OpenWorkspace(databaseName, sdeConnection);
    IFeatureWorkspace featureWorkspace = sdeWorkspace as IFeatureWorkspace;
    IFeatureClass featureClass = featureWorkspace.OpenFeatureClass("TEST.dbo.FEATURES");
    
    Geoprocessor processor = new Geoprocessor();
    processor.OverwriteOutput = true;
    
    ESRI.ArcGIS.ConversionTools.FeatureClassToShapefile conversionTool = 
        new ESRI.ArcGIS.ConversionTools.FeatureClassToShapefile();
        
    conversionTool.Input_Features = featureClass;
    conversionTool.Output_Folder = outputFolder;
    
    try
    {
        processor.Execute(conversionTool, null);
    }
    catch(Exception ex)
    {
        StringBuilder messages = new StringBuilder();
        for(int i = 0; i < processor.MessageCount; i++)
        {
            messages.Append(processor.GetMessage(i) + "\n");
        }
    }
}

Tags: ArcEngine Shapefile IFeatureBuffer IFeatureDataConverter Geoprocessing

Posted on Sat, 01 Aug 2026 17:07:14 +0000 by dbchip2000