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

当使用GDAL读取S-57海图数据时,遇到中文属性值显示为乱码。由于S-57文件中中文以宽字节存储,GDAL按单字节读取导致问题。本文介绍了一个通过自定义转换函数,从宽字节转为单字节的方法,以正确读取并显示中文属性值。
摘要由CSDN通过智能技术生成

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

1366810801_3523.png

图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

#include

#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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值