GDAL 用C#读取shp字段/属性乱码(不用重编译库)

说明

在C#调用gdal1.9.2时,出现中文乱码,搜索原因说是因为gdal是C++写的,编译成C#时没有考虑不同编码字节长度不同的问题。网上搜了一堆解决方案都失败了。网上大致搜集了一下方案:

  1. 修改注册编码,CP936/UTF-8/GB2312/GBK等都有

    OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");   
    OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "");
    
  2. 使用gdal类库中的OCR_F_GetFieldAsString方法

    IntPtr pNativeData = OGR_F_GetFieldAsString(OSGeo.OGR.Feature.getCPtr(fe), index);      
    string str = Marshal.PtrToStringAnsi(pNativeData);
    

但是上面两种还是乱码。

解决方案

中文属性乱码

换种思路搜索发现:C++的char*转C# string中文乱码,可能是因为C++返回的char编码是UTF8,Marshal不支持UTF转换,所以必须先转成Unicode再转成UTF8
查看了一下shapefile的编码文件CPG,发现真的是utf-8编码

// 获取string
IntPtr pchar = OGR_F_GetFieldAsString(OSGeo.OGR.Feature.getCPtr(fe), 38);
// 转unicode编码
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(Marshal.PtrToStringUni(pchar));
// 二进制流转字符串
string value = System.Text.Encoding.UTF8.GetString(bytes);

用这个方法取得的值还有点问题,中文都识别出来了,但还是有部分乱码(值正确,但是vs中显示半截乱码),原因还待深入研究。现在暂时用截取的方法规避了一下。
在这里插入图片描述

中文字段乱码

在读取shp时,遇到中文字段时,调用getName也会出现乱码的情况。

OSGeo.OGR.FieldDefn pFieldDefn = pFeature.GetFieldDefnRef(0);
pFieldDefn.GetName();

参照上面的解决方案,查到了官网api,试着用相似的方法解决了:

在这里插入图片描述

先引入动态库方法,直接使用OGR_Fld_GetNameRef方法

[DllImport("gdal19.dll", EntryPoint = "OGR_Fld_GetNameRef", CallingConvention = CallingConvention.Cdecl)]
public extern static System.IntPtr OGR_Fld_GetNameRef(HandleRef handle);

用OGR_Fld_GetNameRef函数读取字段名,先转为unicode,再转成utf-8

for (int i = 0; i < fieldsCount; i++)
{
    // 获取FieldDefn
    OSGeo.OGR.FieldDefn pFieldDefn = fe.GetFieldDefnRef(i);
    // 解决中文字段乱码,用OGR_Fld函数读取字段名
    IntPtr pcharFld = OGR_Fld_GetNameRef(OSGeo.OGR.FieldDefn.getCPtr(pFieldDefn));
    // 转为unicode二进制
    byte[] bytesFld = System.Text.Encoding.Unicode.GetBytes(Marshal.PtrToStringUni(pcharFld));
    // 二进制转为字符串
    string valueFld = System.Text.Encoding.UTF8.GetString(bytesFld);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值