GDAL/OGR 1.9.0获取shp文件中中文字段值和属性值乱码文件解决

GDAL/OGR 1.9.0又一个新的版本发布,但是又发现了一个对中文支持的问题,在之前的1.8.1版本开始,GDAL开始逐渐加入了对宽字节的支持,或者说是对各种编码的支持,GDAL在默认处理中,将所有的路径字串当作UTF-8编码进行处理,这就是为什么在1.8.0版本开始,如果使用默认编译出来的不支持中文路径了。具体解释参考之前的博客http://blog.csdn.net/liminlu0314/article/details/6610069。在使用1.9.1版本打开中文路径也是有问题的,具体解决方式和上面的一样。

    今天又发现一个新的问题,中文路径的shp格式可以打开,获取的geometry信息也是正确的,但是就是如果属性字段或者属性值中含有中文,悲剧了,整个全是乱码,开始以为还是使用CPLSetConfigOption,发现设置完还是不行:

CPLSetConfigOption(“GDAL_FILENAME_IS_UTF8”,”NO”);
无奈,调试到gdal源代码中,在ogrshapelayer.cpp中OGRShapeLayer类的构造函数中有一个关于编码的选项,构造函数如下:

[cpp] view plaincopyprint?
OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
const char * pszName,
SHPHandle hSHPIn, DBFHandle hDBFIn,
OGRSpatialReference *poSRSIn, int bSRSSetIn,
int bUpdate,
OGRwkbGeometryType eReqType )

{
poDS = poDSIn;
poSRS = poSRSIn;
bSRSSet = bSRSSetIn;

pszFullName = CPLStrdup(pszName);  

hSHP = hSHPIn;  
hDBF = hDBFIn;  
bUpdateAccess = bUpdate;  

iNextShapeId = 0;  
panMatchingFIDs = NULL;  

bCheckedForQIX = FALSE;  
hQIX = NULL;  

bSbnSbxDeleted = FALSE;  

bHeaderDirty = FALSE;  

if( hSHP != NULL )  
{  
    nTotalShapeCount = hSHP->nRecords;  
    if( hDBF != NULL && hDBF->nRecords != nTotalShapeCount )  
    {  
        CPLDebug("Shape", "Inconsistant record number in .shp (%d) and in .dbf (%d)",  
                 hSHP->nRecords, hDBF->nRecords);  
    }  
}  
else   
    nTotalShapeCount = hDBF->nRecords;  

eRequestedGeomType = eReqType;  

bTruncationWarningEmitted = FALSE;  


if( hDBF != NULL && hDBF->pszCodePage != NULL )  
{  
    CPLDebug( "Shape", "DBF Codepage = %s for %s",   
              hDBF->pszCodePage, pszName );  

    // Not too sure about this, but it seems like better than nothing.  
    osEncoding = ConvertCodePage( hDBF->pszCodePage );  
}  

if( CPLGetConfigOption( "SHAPE_ENCODING", NULL ) != NULL )  
    osEncoding = CPLGetConfigOption( "SHAPE_ENCODING", "" );  

if( osEncoding != "" )  
    CPLDebug( "Shape", "Treating as encoding '%s'.", osEncoding.c_str() );  

poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszName),  
                                       hSHP, hDBF, osEncoding );  

/* Init info for the LRU layer mechanism */  
poPrevLayer = NULL;  
poNextLayer = NULL;  
bHSHPWasNonNULL = hSHPIn != NULL;  
bHDBFWasNonNULL = hDBFIn != NULL;  
eFileDescriptorsState = FD_OPENED;  
TouchLayer();  

}
在上面的构造函数中,有下面两句话,调试到此处,
if( CPLGetConfigOption( “SHAPE_ENCODING”, NULL ) != NULL )
osEncoding = CPLGetConfigOption( “SHAPE_ENCODING”, “” );
发现osEncoding = CPLGetConfigOption( “SHAPE_ENCODING”, “” );这句返回的结果是一个叫cp936的编码,那么什么是CP936呢,CP936就是指系统里第936号编码格式(CodePage936),也就是GB2312。在之前是没有设置这个选项的,初步推断,该值可能是根据用户的操作系统来确定的,由于没有英文的操作系统,也不好做测试。

    也就是说,在构造layer的时候,读取的DBF文件中的编码,将DBF编码进行转换,注意上面有句注释:“ // Not too sure about this, but it seems like better than nothing.”,大概意思是说不要太在意这个东西,貌似有总比没有的好,就是这里,让我的中文变成了乱码,情何以堪啊。差不多找到原因了,修改起来就比较方便了,和之前的一样,在打开shp之前,设置一下SHAPE_ENCODING的值为空即可,像下面一样:

CPLSetConfigOption(“SHAPE_ENCODING”,”“);
这样就好了,不知道设置成这样对其他的语言有没有影响,但是对于中文是没有什么问题了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ESRI Shape文件是一种常用的矢量数据格式,它包含了点、线、面等要素和属性信息。为了处理这种格式的数据,我们可以使用GDAL/OGR库。本文将介绍如何使用C#语言和GDAL/OGR库读写ESRI Shape文件。 一、安装GDAL/OGRGDAL/OGR库是一个开源的地理信息系统扩展库,它可以读写各种GIS数据格式。我们可以从官网(https://gdal.org/download.html)下载最新的二进制版本,并进行安装。 二、创建工作空间 在C#使用GDAL/OGR库进行ESRI Shape文件的读写,需要先创建一个工作空间。工作空间是一个抽象的概念,它代表了一个包含多个数据集的环境。我们可以使用以下代码创建一个工作空间: ```csharp using OSGeo.OGR; using OSGeo.GDAL; Gdal.AllRegister(); Ogr.RegisterAll(); string workspace = @"C:\data\shapefiles"; Driver driver = Ogr.GetDriverByName("ESRI Shapefile"); DataSource dataSource = driver.Open(workspace, 0); ``` 这里使用了GDAL/OGR的`Driver`、`DataSource`和`Gdal`等类。首先,我们调用`Gdal.AllRegister()`方法和`Ogr.RegisterAll()`方法注册GDAL/OGR的所有驱动程序。然后,我们指定了一个路径作为工作空间,并使用`Ogr.GetDriverByName()`方法获取ESRI Shapefile驱动程序。最后,我们调用`driver.Open()`方法打开工作空间,并将返回的`DataSource`对象存储到`dataSource`变量。 三、读取ESRI Shape文件创建了工作空间之后,我们可以使用`dataSource`对象读取ESRI Shape文件的要素和属性信息。以下代码演示了如何读取ESRI Shape文件的所有点要素: ```csharp Layer layer = dataSource.GetLayerByName("points"); Feature feature = null; while ((feature = layer.GetNextFeature()) != null) { Geometry geometry = feature.GetGeometryRef(); double x = geometry.GetX(0); double y = geometry.GetY(0); Console.WriteLine($"Point ({x}, {y})"); } ``` 这里使用了GDAL/OGR的`Layer`、`Feature`和`Geometry`等类。首先,我们使用`dataSource.GetLayerByName()`方法获取名为“points”的图层,并将返回的`Layer`对象存储到`layer`变量。然后,我们使用`layer.GetNextFeature()`方法循环遍历图层的所有要素,并将返回的`Feature`对象存储到`feature`变量。接着,我们使用`feature.GetGeometryRef()`方法获取要素的几何体,并将返回的`Geometry`对象存储到`geometry`变量。最后,我们使用`geometry.GetX(0)`和`geometry.GetY(0)`方法获取要素的坐标,并将其打印到控制台上。 四、写入ESRI Shape文件 在读取了ESRI Shape文件之后,我们可以使用`dataSource`对象写入新的要素和属性信息。以下代码演示了如何创建一个新的ESRI Shape文件,并向其添加一个点要素: ```csharp Layer layer = dataSource.CreateLayer("new_points", null, wkbGeometryType.wkbPoint, null); FieldDefn fieldDefn = new FieldDefn("name", FieldType.OFTString); layer.CreateField(fieldDefn, 1); Feature feature = new Feature(layer.GetLayerDefn()); Geometry geometry = new Point(121.5, 31.2); feature.SetGeometry(geometry); feature.SetField("name", "Shanghai"); layer.CreateFeature(feature); dataSource.SyncToDisk(); ``` 这里使用了GDAL/OGR的`FieldDefn`、`Point`和`wkbGeometryType`等类。首先,我们使用`dataSource.CreateLayer()`方法创建一个名为“new_points”的图层,并将返回的`Layer`对象存储到`layer`变量。然后,我们使用`new FieldDefn("name", FieldType.OFTString)`语句创建一个名为“name”的字符串型属性。接着,我们使用`layer.CreateField()`方法创建一个新的属性字段,并将`fieldDefn`变量和`1`参数传递给该方法。接下来,我们使用`new Point(121.5, 31.2)`语句创建一个新的点几何体,并将其存储到`geometry`变量。然后,我们使用`new Feature(layer.GetLayerDefn())`语句创建一个新的要素,并将其存储到`feature`变量。接着,我们使用`feature.SetGeometry(geometry)`方法设置要素的几何体。最后,我们使用`feature.SetField("name", "Shanghai")`方法设置要素的属性,并使用`layer.CreateFeature(feature)`方法将要素添加到图层。最后,我们使用`dataSource.SyncToDisk()`方法将修改保存到磁盘。 总结 本文介绍了如何使用C#语言和GDAL/OGR库读写ESRI Shape文件。我们首先创建了一个工作空间,并使用它读取了ESRI Shape文件的点要素。然后,我们创建了一个新的ESRI Shape文件,并向其添加了一个点要素。使用GDAL/OGR库可以方便地处理各种GIS数据格式,为GIS应用程序的开发提供了便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值