• GDAL读取S57海图数据中文属性值乱码问题解决


    使用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,"");     //设置本地默认Locale
    	int 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,"");     //设置本地默认Locale
    	int 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;
    }

  • 相关阅读:
    1028 List Sorting (25分)
    CSS通用样式类讲解
    异常处理机制
    修饰符及接口和内部类
    用python实现基础的数据类型
    类属性和实例化属性
    命名空间和作用域
    python super()函数有无参数的调用
    编写html页面常常犯的错误
    多态
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6313961.html
Copyright © 2020-2023  润新知