.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.");
}
}