GDAL写入FileGDB中文属性乱码问题
GDAL库中提供了两个驱动来访问FileGDB格式,一个是基于ESRI提供的FileGDBAPI库来访问gdb,支持读写,另外一个是gdal自己写的OpenFileGDB驱动来访问,只支持读,不支持写。
本文主要是针对ESRI提供的FileGDBAAPI库的驱动来说。只用FileGDB驱动创建gdb时,再写入中文属性值时,会出现乱码,下面给出解决方案。
在FileGDB的文件夹中,有个FGdbUtils.cpp的问题,其中定义了两个函数,原型如下:
std::wstring StringToWString(const std::string& s);
std::string WStringToString(const std::wstring& s);
这两个函数的目的就是宽字节和窄字节相互转换。但是在转换过程中对于编码指定的问题导致转换结果不对,从而导致写入gdb文件中的中文属性值乱码。
下面是gdal库中对于上述两个函数的实现:
/*************************************************************************/
/* StringToWString() */
/*************************************************************************/
std::wstring StringToWString(const std::string& utf8string)
{
wchar_t* pszUTF16 = CPLRecodeToWChar( utf8string.c_str(), CPL_ENC_UTF8, CPL_ENC_UCS2);
std::wstring utf16string = pszUTF16;
CPLFree(pszUTF16);
return utf16string;
}
/*************************************************************************/
/* WStringToString() */
/*************************************************************************/
std::string WStringToString(const std::wstring& utf16string)
{
char* pszUTF8 = CPLRecodeFromWChar( utf16string.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8 );
std::string utf8string = pszUTF8;
CPLFree(pszUTF8);
return utf8string;
}
从上述代码中可以看出,GDAL库中将所有的字符串全部默认为UTF-8的编码,然后直接进行了转换,如果使用中文,且没有使用UTF-8对中文进行编码,那么再使用上述两个函数进行转换时,肯定会出现乱码问题,针对这个问题,修改上面的代码中,添加了一个配置项,类似shp文件的SHP_ENCODING配置项用于指定输入的字符编码,此处配置项名称改为FILEGDB_ENCODING,将上述两个函数修改为如下:
/*************************************************************************/
/* StringToWString() */
/*************************************************************************/
std::wstring StringToWString(const std::string& utf8string)
{
const char* pszFileGDBEncoding = CPLGetConfigOption("FILEGDB_ENCODING", CPL_ENC_UTF8);
char* pszUTF8String = NULL;
if (EQUAL(pszFileGDBEncoding, CPL_ENC_UTF8))
pszUTF8String = CPLStrdup(utf8string.c_str());
else
pszUTF8String = CPLRecode(utf8string.c_str(), pszFileGDBEncoding, CPL_ENC_UTF8);
wchar_t* pszUTF16 = CPLRecodeToWChar( pszUTF8String, CPL_ENC_UTF8, CPL_ENC_UCS2);
std::wstring utf16string = pszUTF16;
CPLFree(pszUTF16);
CPLFree(pszUTF8String);
return utf16string;
}
/*************************************************************************/
/* WStringToString() */
/*************************************************************************/
std::string WStringToString(const std::wstring& utf16string)
{
char* pszUTF8 = CPLRecodeFromWChar( utf16string.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8 );
std::string utf8string = pszUTF8;
CPLFree(pszUTF8);
const char* pszFileGDBEncoding = CPLGetConfigOption("FILEGDB_ENCODING", CPL_ENC_UTF8);
if (EQUAL(pszFileGDBEncoding, CPL_ENC_UTF8))
return utf8string;
else
{
char* pszLocalString = CPLRecode(utf8string.c_str(), CPL_ENC_UTF8, pszFileGDBEncoding);
utf8string = pszLocalString;
CPLFree(pszLocalString);
return utf8string;
}
return utf8string;
}
修改完保存,重新编译GDAL,如果使用的插件,直接编译File GDB的插件dll,将生成的ogr_filegdb.dll放到gdal的插件目录即可。
在使用的时候,设置配置项FILEGDB_ENCODING=CP936(GBK)等即可。
命令行使用:–config FILEGDB_ENCODING CP936
代码中使用:CPLSetConfigOption(“FILEGDB_ENCODING”, “CP936”)
转载自:https://blog.csdn.net/liminlu0314/article/details/55508358