zoukankan      html  css  js  c++  java
  • GDAL读取S57海图数据中文属性值乱码问题解决(续)

    上篇博文中的代码使用了函数wcstombs来进行处理,今天发现GDAL库里面提供了宽字节转单字节的函数,名字叫CPLRecodeFromWChar(这个函数需要libiconv库的支持,也就是在编译GDAL的时候需要把libiconv库一起编译)。本以为C#语言也可以使用,结果很悲剧的发现,C#的提供的接口中没有相关的函数,看来使用C#的同学有点悲剧了。

    需要说明的是,需要先用函数CPLRecodeFromWChar将宽字节转为UTF8,然后再使用函数CPLRecode将UTF8转为汉字编码(CP936)。

    程序依旧是昨天的那个,函数全部换成GDAL的函数,代码如下:

    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();   //获取属性字段值  
    
    		// 为了演示说明,就只输出乱码的属性值 
    		const char* pszAttValue = poFeature->GetFieldAsString("NOBJNM"); 
    		size_t size = strlen(pszAttValue);
    		if (size != 0)
    		{
    			char* pszValue = new char[size];
    			memcpy(pszValue, pszAttValue, size);
    			pszValue[size-1] = '\0';
    
    			char *pszGetUTF8 = CPLRecodeFromWChar( (const wchar_t*)pszValue, CPL_ENC_UCS2, CPL_ENC_UTF8);
    			pszAttValue = CPLRecode( pszGetUTF8, CPL_ENC_UTF8, "");
    			delete []pszValue;
    		}
    
    		printf("%s\n", pszAttValue); 
    
    		OGRFeature::DestroyFeature( poFeature );  
    		poFeature = poLayer->GetNextFeature();  
    	}  
    
    	OGRDataSource::DestroyDataSource( poDS );  
    	return 0;  
    }
    下图是执行输出的结果,和使用QGIS打开对比。

    通过上面的方式是可以解决这个问题,不过稍微有点麻烦,需要在每次获取属性值的时候都要进行判断。我们可以直接修改GDAL库中的代码,这样在读取的时候直接就是汉字编码。找了一下午,在GDAL库的源码中文件gdal-1.9.2\ogr\ogrsf_frmts\s57\s57reader.cpp行883左右,修改为下面:

    		// Add By liml 2013-04-25 Convert UCS-2 to Utf-8
    		const char* pachBuffer = poRecord->GetStringSubfield("NATF",0,"ATVL",iAttr);
    		if( EQUAL(pszAcronym, "NOBJNM"))
    		{
    			size_t nLength = strlen(pachBuffer);
    
    			char* pszValue = new char[nLength];
    			memcpy(pszValue, pachBuffer, nLength);
    			pszValue[nLength-1] = '\0';
    
    			char *pszGetUTF8 = CPLRecodeFromWChar( (const wchar_t*)pszValue, CPL_ENC_UCS2, CPL_ENC_UTF8);
    			pachBuffer = CPLRecode( pszGetUTF8, CPL_ENC_UTF8, CPL_ENC_LOCALE);
    			delete []pszValue;
    		}
    		// Add By liml 2013-04-25
    
            poFeature->SetField( pszAcronym, pachBuffer);
    下面是使用ogrinfo输出的对比情况,左边是没修改时输出的,右边是修改后输出的。

    虽然这么修改是可以解决这个问题,但是不知道会不会引起其他的副作用。等发现了再修改吧。修改之后的GDAL库已经上传至我的资源中心,有需要的同学可以自行去下载。

  • 相关阅读:
    [原创]设计模式建造者模式
    [原创]设计模式抽象工厂模式
    svn的branch/tag(转)
    [原创]设计模式访问者模式
    自定义安装python,退格,方向键无法正常使用(转)
    关于UDP 数据包长度的选择
    cent os 查看服务器信息
    【开源】QuickPager 分页控件的内部结构,和OO原则与设计模式
    【思路】表单控件和查询控件,整理一下思路。
    【测试】两种数据库,四种分页算法的效率比较
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6313960.html
Copyright © 2011-2022 走看看