C#編譯版GDAL讀取矢量數據導入PG數據庫中文字段亂碼解決方案

最近在研究GDAL,在嘗試將矢量數據導入到pg中時出現了中文字段亂碼的問題。亂碼類似於下圖:

百度了一下,大部分都是說要設置

Gdal.SetConfigOption("SHAPE_ENCODING", string.Empty);

但是我設置完之後完全沒用,甚至還不如之前,一個漢字都沒了全變成亂碼了。我有跟斷點發現我從源數據裏讀出來的數據就已經是亂碼了,感覺有點拉閘。最後在一個羣友的指導下,通過DllImport的方式引用原本的gdal204.dll(不同的GDAL版本數字不同)文件,使用裏面的字段讀取函數來獲取字段的值。雖然一開始也是亂碼,但是上面的編碼設置終於起作用了,加上後終於正常了。個人推測是GDAL的C#編譯版在讀取中文字段的時候有問題,但是具體什麼原因我也沒搞明白。具體代碼如下。

[DllImport("gdal204.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr OGR_F_GetFieldAsString(HandleRef handle, int fieldIdx);

        private static void ImportVectorData2PG()
        {
            Ogr.RegisterAll();

            // 支持中文路徑
            // Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");

            // 使字段支持中文
            Gdal.SetConfigOption("SHAPE_ENCODING", string.Empty);

            // 讀取矢量文件信息
            string sourceVector = @"D:\DTLFolder\ogrtest.shp";
            DataSource srcVectorDs = Ogr.Open(sourceVector, 0);

            // 只讀取第一個圖層
            Layer srcVectorLy = srcVectorDs.GetLayerByIndex(0);
            FeatureDefn srcVectorDefn = srcVectorLy.GetLayerDefn();
            string layerName = srcVectorLy.GetName();
            SpatialReference spatialReference = srcVectorLy.GetSpatialRef();
            wkbGeometryType wkbGeometryType = srcVectorLy.GetGeomType();

            // 讀取PG庫信息
            string connStr = "PG:dbname=yanshi host=localhost port=5432 user=postgres password=postgres";
            OSGeo.OGR.Driver drv = Ogr.GetDriverByName("PostgreSQL");
            DataSource dataSource = drv.Open(connStr, 1); // 0是隻讀?
            Layer layer = dataSource.GetLayerByName(layerName);

            // 沒有同名圖層則創建同結構新圖層
            if (layer == null)
            {
                layer = dataSource.CreateLayer(layerName, spatialReference, wkbGeometryType, null);
                int fieldCount = srcVectorDefn.GetFieldCount();
                for (int i = 0; i < fieldCount; i++)
                {
                    FieldDefn fieldDefn = srcVectorDefn.GetFieldDefn(i);
                    layer.CreateField(fieldDefn, 1);
                }

                int geoFieldCount = srcVectorDefn.GetGeomFieldCount();
                for (int i = 0; i < geoFieldCount; i++)
                {
                    GeomFieldDefn geomFieldDefn = srcVectorDefn.GetGeomFieldDefn(i);
                    layer.CreateGeomField(geomFieldDefn, 1);
                }
            }

            // 循環賦值創建
            Feature feature = null;
            while ((feature = srcVectorLy.GetNextFeature()) != null)
            {
                FeatureDefn featureDefn = layer.GetLayerDefn();
                Feature newFeature = new Feature(featureDefn);
                for (int i = 0; i < srcVectorDefn.GetFieldCount(); i++)
                {
                    FieldDefn oDefn = srcVectorDefn.GetFieldDefn(i);
                    FieldType type = oDefn.GetFieldType();
                    switch (type)
                    {
                        case FieldType.OFTInteger:
                            newFeature.SetField(i, feature.GetFieldAsInteger(i));
                            break;
                        case FieldType.OFTReal:
                            newFeature.SetField(i, feature.GetFieldAsDouble(i));
                            break;
                        case FieldType.OFTString:
                            string val = Marshal.PtrToStringAnsi(OGR_F_GetFieldAsString(Feature.getCPtr(feature), i));
                            newFeature.SetField(i, val);
                            break;
                        default:
                            newFeature.SetField(i, feature.GetFieldAsString(i));
                            break;
                    }
                }

                for (int i = 0; i < srcVectorDefn.GetGeomFieldCount(); i++)
                {
                    Geometry geometry = feature.GetGeomFieldRef(i);
                    newFeature.SetGeometry(geometry);
                }

                layer.CreateFeature(newFeature);
            }
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章