.NET C# 使用GDAL将mdb转换gdb数据

.NET C# 使用GDAL将mdb转换gdb数据

目录

  • [.NET C# 使用GDAL将mdb转换gdb数据](# 使用GDAL将mdb转换gdb数据)
    • [1 环境](#1 环境)
    • [2 Nuget](#2 Nuget)
    • [3 Code](#3 Code)

1 环境

VisualStudio2022 + .NET6 + GDAL 3.8.5

2 Nuget

3 Code

FeatureExtension.cs

csharp 复制代码
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

csharp 复制代码
public enum FeatureDatastoreType
{
    Other,
    GDB
}

MDB2GDB.cs

csharp 复制代码
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.");
    }
}
相关推荐
CSharp精选营11 小时前
.NET 8 与 .NET 9 支持终止倒计时:开发者需要了解什么
.net·lts·.net8·.net9·码农刚子·升级迁移·sts·支持终止
tntxia3 天前
GIS 坐标系
gis
hez20103 天前
在 .NET 上构建超大托管数组
c#·.net·.net core·gc·clr
ttkwzyttk5 天前
GDB TUI窗口管理
gdb
ttkwzyttk6 天前
GDB观察点与捕获点使用
gdb
雨落倾城夏未凉8 天前
第四章c#方法-参数数组和可选参数(16)
后端·c#
唐青枫9 天前
线程不是越多越快:C#.NET Thread 生命周期、同步与后台工作线程实战
c#·.net
唐青枫10 天前
别只会反射:C#.NET Emit 动态生成代码实战详解
c#·.net
Caco_D10 天前
一行代码抓遍全网 20 个热榜!Aneiang.Pa 4.0 发布 — 极简 .NET 爬虫库
爬虫·.net