加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

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

(2012-08-14 17:06:39)
标签:

杂谈

分类: GDAL

 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类的构造函数中有一个关于编码的选项,构造函数如下:

 

  1. OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,  
  2.                               const char pszName,  
  3.                               SHPHandle hSHPIn, DBFHandle hDBFIn,   
  4.                               OGRSpatialReference *poSRSIn, int bSRSSetIn,  
  5.                               int bUpdate,  
  6.                               OGRwkbGeometryType eReqType  
  7.   
  8.  
  9.     poDS poDSIn;  
  10.     poSRS poSRSIn;  
  11.     bSRSSet bSRSSetIn;  
  12.   
  13.     pszFullName CPLStrdup(pszName);  
  14.       
  15.     hSHP hSHPIn;  
  16.     hDBF hDBFIn;  
  17.     bUpdateAccess bUpdate;  
  18.   
  19.     iNextShapeId 0;  
  20.     panMatchingFIDs NULL;  
  21.   
  22.     bCheckedForQIX FALSE;  
  23.     hQIX NULL;  
  24.   
  25.     bSbnSbxDeleted FALSE;  
  26.   
  27.     bHeaderDirty FALSE;  
  28.   
  29.     ifhSHP != NULL  
  30.      
  31.         nTotalShapeCount hSHP->nRecords;  
  32.         ifhDBF != NULL && hDBF->nRecords != nTotalShapeCount  
  33.          
  34.             CPLDebug("Shape""Inconsistant record number in .shp (%d) and in .dbf (%d)" 
  35.                      hSHP->nRecords, hDBF->nRecords);  
  36.          
  37.      
  38.     else   
  39.         nTotalShapeCount hDBF->nRecords;  
  40.       
  41.     eRequestedGeomType eReqType;  
  42.   
  43.     bTruncationWarningEmitteFALSE;  
  44.   
  45.       
  46.     ifhDBF != NULL && hDBF->pszCodePage != NULL  
  47.      
  48.         CPLDebug( "Shape""DBF Codepage %s for %s"  
  49.                   hDBF->pszCodePage, pszName );  
  50.   
  51.         // Not too sure about this, but it seems like better than nothing.  
  52.         osEncoding ConvertCodePage( hDBF->pszCodePage );  
  53.      
  54.       
  55.     ifCPLGetConfigOption( "SHAPE_ENCODING"NULL != NULL  
  56.         osEncoding CPLGetConfigOption( "SHAPE_ENCODING""" );  
  57.   
  58.     ifosEncoding != ""  
  59.         CPLDebug( "Shape""Treating as encoding '%s'."osEncoding.c_str() );  
  60.   
  61.     poFeatureDefn SHPReadOGRFeatureDefn( CPLGetBasename(pszName),  
  62.                                            hSHP, hDBF, osEncoding );  
  63.   
  64.       
  65.     poPrevLayer NULL;  
  66.     poNextLayer NULL;  
  67.     bHSHPWasNonNULL hSHPIn != NULL;  
  68.     bHDBFWasNonNULL hDBFIn != NULL;  
  69.     eFileDescriptorsState FD_OPENED;  
  70.     TouchLayer();  
  71.  
        在上面的构造函数中,有下面两句话,调试到此处,
  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

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有