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")
新聞熱點
疑難解答