.NET C# 使用GDAL将mdb转换gdb数据
目录
- .NET C# 使用GDAL将mdb转换gdb数据
- 1 环境
- 2 Nuget
- 3 Code
1 环境
VisualStudio2022 + .NET6 + GDAL 3.8.5
2 Nuget
3 Code
FeatureExtension.cs
public static class FeatureExtension
{[DllImport("gdal.dll", EntryPoint = "OGR_F_GetFieldAsBinary", CallingConvention = CallingConvention.Cdecl)]public extern static IntPtr OGR_F_GetFieldAsBinary(HandleRef handle, int index, out int byteCount);[DllImport("gdal.dll", EntryPoint = "OGR_F_GetFieldAsString", CallingConvention = CallingConvention.Cdecl)]public extern static IntPtr OGR_F_GetFieldAsString(HandleRef handle, int i);[DllImport("gdal.dll", EntryPoint = "CPLStrnlen", CallingConvention = CallingConvention.Cdecl)]public extern static uint CPLStrnlen(IntPtr handle, uint nMaxLen);public static byte[] GetFieldAsBinary(this Feature feature, int index, FeatureDatastoreType datastoreType){if (datastoreType == FeatureDatastoreType.GDB){int byteCount = 0;IntPtr pIntPtr = OGR_F_GetFieldAsBinary(Feature.getCPtr(feature), index, out byteCount);byte[] byteArray = new byte[byteCount];Marshal.Copy(pIntPtr, byteArray, 0, byteCount);return byteArray;}else{IntPtr pchar = OGR_F_GetFieldAsString(Feature.getCPtr(feature), index);int length = (int)CPLStrnlen(pchar, uint.MaxValue);byte[] byteArray = new byte[length];Marshal.Copy(pchar, byteArray, 0, length);return byteArray;}}public static byte[] GetFieldAsBinary(this Feature feature, string fieldName, FeatureDatastoreType datastoreType){int index = feature.GetFieldIndex(fieldName);if (datastoreType == FeatureDatastoreType.GDB){int byteCount = 0;IntPtr pIntPtr = OGR_F_GetFieldAsBinary(Feature.getCPtr(feature), index, out byteCount);byte[] byteArray = new byte[byteCount];Marshal.Copy(pIntPtr, byteArray, 0, byteCount);return byteArray;}else{IntPtr pchar = OGR_F_GetFieldAsString(Feature.getCPtr(feature), index);int length = (int)CPLStrnlen(pchar, uint.MaxValue);byte[] byteArray = new byte[length];Marshal.Copy(pchar, byteArray, 0, length);return byteArray;}}
}
FeatureDatastoreType.cs
public enum FeatureDatastoreType
{Other,GDB
}
MDB2GDB.cs
public class MDB2GDB
{public void Convert(string mdbFilePath, string gdbFilePath){// 注册所有驱动GdalConfiguration.ConfigureGdal();GdalConfiguration.ConfigureOgr();// 注册编码提供程序以支持GBK编码Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);// 打开MDB数据源var mdbDriver = Ogr.GetDriverByName("PGeo");if (mdbDriver == null){Console.WriteLine("MDB driver is not available.");return;}DataSource mdbDataSource = null;try{mdbDataSource = mdbDriver.Open(mdbFilePath, 0);}catch(Exception ex){Console.WriteLine("Failed to open MDB file.");return;}// 创建GDB数据源Driver gdbDriver = Ogr.GetDriverByName("OpenFileGDB");if (gdbDriver == null){Console.WriteLine("OpenFileGDB driver is not available.");return;}DataSource gdbDataSource = null;try{gdbDataSource = gdbDriver.CreateDataSource(gdbFilePath, null);}catch(Exception ex){Console.WriteLine("Failed to create GDB file.");return;}// 遍历MDB数据源中的所有图层并复制到GDB数据源for (int i = 0; i < mdbDataSource.GetLayerCount(); i++){Layer mdbLayer = mdbDataSource.GetLayerByIndex(i);string lyrName = mdbLayer.GetName();Layer gdbLayer = gdbDataSource.CreateLayer(lyrName, mdbLayer.GetSpatialRef(), mdbLayer.GetGeomType(), null);Console.WriteLine($"Source Layer: {lyrName}");// 复制字段定义FeatureDefn mdbFeatureDefn = mdbLayer.GetLayerDefn();for (int j = 0; j < mdbFeatureDefn.GetFieldCount(); j++){FieldDefn fieldDefn = mdbFeatureDefn.GetFieldDefn(j);string fieldName = fieldDefn.GetName();Console.WriteLine($"Source Field: {fieldDefn.GetName()} - Right Field: {fieldName}");gdbLayer.CreateField(fieldDefn, 1);}mdbLayer.ResetReading();// 复制要素Feature mdbFeature;while ((mdbFeature = mdbLayer.GetNextFeature()) != null){Feature gdbFeature = new Feature(gdbLayer.GetLayerDefn());gdbFeature.SetFrom(mdbFeature, 1);// 显式设置字段的字符编码,这里为解决MDB数据中的中文使用GBK编码导致的中文乱码问题for (int j = 0; j < gdbFeature.GetFieldCount(); j++){FieldType fieldType = gdbFeature.GetFieldDefnRef(j).GetFieldType();if (fieldType == FieldType.OFTString || fieldType == FieldType.OFTWideString){byte[] bytes = gdbFeature.GetFieldAsBinary(j, FeatureDatastoreType.Other);string fieldValue = Encoding.GetEncoding("GBK").GetString(bytes);gdbFeature.SetField(j, fieldValue);}}//如果MDB数据编码使用的utf8则不需要上面这段代码gdbLayer.CreateFeature(gdbFeature);mdbFeature.Dispose();gdbFeature.Dispose();}}// 释放资源mdbDataSource.Dispose();gdbDataSource.Dispose();Console.WriteLine("Conversion completed successfully.");}
}