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

 

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