原文链接: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;
}
}