zoukankan      html  css  js  c++  java
  • 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类的构造函数中有一个关于编码的选项,构造函数如下:

    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","");

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


  • 相关阅读:
    H264关于RTP协议的实现
    RTSP交互命令简介及过程参数描述
    RTSP协议详解
    TCP 协议中MSS的理解
    RTSP 协议分析
    Linux下/etc/resolv.conf 配置DNS客户
    371. Sum of Two Integers
    python StringIO
    高效的两段式循环缓冲区──BipBuffer
    JavaScript Lib Interface (JavaScript系统定义的接口一览表)
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6314028.html
Copyright © 2011-2022 走看看