使用GDAL读取S-57海图数据时,对于属性表中的中文属性值读出来是乱码。如图1所示。

图1 S57海图数据中文乱码字段

通过调试代码发现,S-57文件中的中文是按照宽字节存储在文件中,而GDAL在读取时统一按照单字节来读取,这样就直接导致了中文属性值的乱码。比如这里有个字段属性值为“北京市”,读出来显示为“S琋^”,对应的十六进制为“0x17 0x53 0xac 0x4e 0x02 0x5e 0x1f 0x00”。

本以为GDAL中会有个设置选项来设置编码,S57的源码翻遍了也没找到设置选项,看来只能自力更生了,那就是自己写个转换函数来进行转换。修改GDAL库的源码工作量有点大,还是直接在外面处理吧。首先我们要写一个把宽字节转为单字节的函数。代码如下:

string ConvertWchar2Char(const wstring &str)
{size_t len = wcstombs(NULL, str.c_str(), 0)*2 + 1;char *pszDst = new char[len];setlocale(LC_ALL,"");     //设置本地默认Localeint len1 = wcstombs(pszDst, str.c_str(), len);setlocale(LC_ALL,"C");     //默认if(len1 == -1){delete []pszDst;throw runtime_error("wcstombs(): unable to convert character");}string strChar = string(pszDst, len);delete []pszDst;return strChar;
}

有了上面的函数,我们就可以在读取属性值后,调用上面的函数进行转换就OK了。需要注意的是,GDAL中获取的属性值返回值是一个const char*格式,表面看起来是个单字节,但实质内存存储的确是多字节,所以我们需要强制类型转换转为多字节,代码片段如下:

 const char* pszValue = poFeature->GetFieldAsString("NOBJNM");wstring strwValue = (const wchar_t*)pszValue;//转换为单字节string strValue = ConvertWchar2Char(strwValue);

第一句返回的是一个const char*,然后直接强制类型转为const wchar_t*类型,然后构造一个wstring类型。最后使用上面的函数进行转换即可得到最终的结果值。完整的测试代码如下:

#include <stdio.h>
#include <string>#include "ogrsf_frmts.h"
#include "ogr_spatialref.h"using namespace std;string ConvertWchar2Char(const wstring &str)
{size_t len = wcstombs(NULL, str.c_str(), 0)*2 + 1;char *pszDst = new char[len];setlocale(LC_ALL,"");     //设置本地默认Localeint len1 = wcstombs(pszDst, str.c_str(), len);setlocale(LC_ALL,"C");     //默认if(len1 == -1){delete []pszDst;throw runtime_error("wcstombs(): unable to convert character");}string strChar = string(pszDst, len);delete []pszDst;return strChar;
}int ReadS57()
{  CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");  OGRRegisterAll();  //打开数据  const char* pszS57 = "D:\\C1100102.000";  OGRDataSource *poDS = OGRSFDriverRegistrar::Open(pszS57, FALSE );  if( poDS == NULL )  {  printf( "Open failed.\n" );  return 1;  }  // 获取有中文属性值的图层  OGRLayer *poLayer = poDS->GetLayerByName( "BUAARE" );  if( poLayer == NULL )  {  printf( "Get Layer failed.\n" );  OGRDataSource::DestroyDataSource( poDS );  return 1;  }  poLayer->ResetReading();  OGRFeature *poFeature = poLayer->GetNextFeature();  while (poFeature != NULL )  {  OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();   //获取属性字段值  // 为了演示说明,就只输出乱码的属性值  string strValue = poFeature->GetFieldAsString("NOBJNM"); if (strValue != ""){char* pszValue = (char*)strValue.c_str();size_t ilast = strlen(pszValue);pszValue[ilast-1] = '\0';wstring strwValue = (const wchar_t*)pszValue;  //转换为单字节  strValue = ConvertWchar2Char(strwValue);  }printf("%s\n", strValue.c_str());  OGRFeature::DestroyFeature( poFeature );  poFeature = poLayer->GetNextFeature();  }  OGRDataSource::DestroyDataSource( poDS );  return 0;
}int main()
{// 先测试转换函数是否正常工作const char* pszValue = "S琋^";wstring str =  (const wchar_t*)pszValue;string strTemp = ConvertWchar2Char(str);printf("%s\n", strTemp.c_str());wstring str1 = L"Hello1234";strTemp = ConvertWchar2Char(str1);printf("%s\n", strTemp.c_str());// 读取S57海图数据ReadS57();return 0;
}

GDAL读取S-57海图数据中文属性值乱码问题解决相关推荐

  1. gdal mysql乱码_GDAL读取S-57海图数据中文属性值乱码问题解决(续)

    上篇博文中的代码使用了函数wcstombs来进行处理,今天发现GDAL库里面提供了宽字节转单字节的函数,名字叫CPLRecodeFromWChar(这个函数需要libiconv库的支持,也就是在编译G ...

  2. GDAL读取S-57海图数据中文属性值乱码问题解决(续)

    上篇博文中的代码使用了函数wcstombs来进行处理,今天发现GDAL库里面提供了宽字节转单字节的函数,名字叫CPLRecodeFromWChar(这个函数需要libiconv库的支持,也就是在编译G ...

  3. GDAL C#读取shp中文属性值乱码问题

    GDAL的C#版本读取shp中,如果属性值中含有中文,读出来有可能是乱码的问题,根据SWIG生成的C#代码调试发现问题所在,在Ogr.cs文件中有这么一个函数,代码如下: internal stati ...

  4. GDAL C#中文路径,中文属性名称乱码问题

    昨天写的博客,将C#读取shp中文属性值乱码的问题应该可以解决,博客地址为:http://blog.csdn.net/liminlu0314/article/details/54096119,然后又测 ...

  5. java.net.url 中文乱码,.Net获取URL中文参数值的乱码问题解决方法总结

    本文总结分析了.Net获取URL中文参数值的乱码问题解决方法.分享给大家供大家参考,具体如下: 解决方法: 1.设置web.config文件 2.传递中文之前,将要传递的中文参数进行编码,在接收时再进 ...

  6. oracle 菱形乱码,Ubuntu Server 16.04中文方块菱形乱码问题解决

    Ubuntu Server 16.04中文方块菱形乱码问题解决 这里只讲tty的中文方块乱码 默认的tty只能显示一个字节128或256字符,你可以用setfont命令去改tty的字体,但是永远只能局 ...

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

    GDAL/OGR 1.9.0又一个新的版本发布,但是又发现了一个对中文支持的问题,在之前的1.8.1版本开始,GDAL开始逐渐加入了对宽字节的支持,或者说是对各种编码的支持,GDAL在默认处理中,将所 ...

  8. SpringBoot中通过ConfigurationProperties注解的方式读取application.yml中配置的属性值

    场景 在SpringBoot后台项目中,某些固定的属性需要配置在配置文件application.yml中. 比如上传到服务器的文件路径. 然后在其他业务代码中比如上传文件接口中需要或者到配置的这个属性 ...

  9. Oracle 11g中文繁体特殊乱码问题解决

    @](特殊乱码问题解决方式) 遇到问题 最近老大给了一个同事写的操作数据库的程序,因为疫情原因而进行公司员工的锁卡与恢复,需要Oracle环境. 1>在此之前一直做的Excel数据导入工作,简体 ...

最新文章

  1. 【读书笔记《Bootstrap 实战》】3.优化站点资源、完成响应式图片、让传送带支持手势...
  2. 玩远程 可视对讲系统几大新兴应用分析
  3. python统计代码行数
  4. APK加密方法:某社交类Android APP加密分享
  5. 2020新年发红包Java实现
  6. spring mvc学习(36):jstl的jar包的下载
  7. python dataframe 取每行的最大值,在python数据框中的每一行中查找最大值
  8. Python输出带颜色字体
  9. java三目表达式_史上最强《Java 开发手册》泰山版王者归来
  10. mysql 出现 “1067 - Invalid default value for ‘UPDATE_TIME‘ “ 错误提示的解决办法
  11. 东莞市理工学校计算机分数线,东莞公办中职学校分数线公布,理工学校两专业613分领跑全市...
  12. java中properties类_Java中的Properties类详解
  13. javascript中实现动画是settimeout(递归)还是用setinterval好?
  14. 计算机网络最早出现在哪个年代
  15. 大师级思考者是怎么探索事物本质的?
  16. springboot 解决 NoClassDefFoundError: redis/clients/jedis/util/SafeEncoder
  17. ChatGPT 从入门到精通
  18. java 三边求面积_已知三角形的三边长如何求面积?
  19. Delivering Smiles:亚马逊的温暖进行时
  20. 普通家庭,千万不要投入大量时间和金钱,让孩子去苦学和培养AI机器人编程了...

热门文章

  1. 计算机系统集成 行业标准,行业标准信息服务平台
  2. 技校毕业是什么学历_技校毕业是什么学历 属于什么文凭
  3. ros indigo 学习笔记
  4. android bin目录是什么,android bin目录下的.ap_是神马文件?
  5. shell中encoding=utf-8_如何在Linux中将文件转换为UTF-8编码
  6. 找出所有子集的异或总和再求和
  7. ubuntu之搭建http服务器apache2
  8. PCL之K维树--KD-tree
  9. html设置多列布局间隙,css设置多列等高布局的方法示例
  10. amazeUI 复择框问题解决