GDAL在GIS界是赫赫有名的,它即有操作栅格的GDAL组件,又有读取矢量的OGR类库,可谓"文武双全",连 ESRI也在使用,跨平台、开源、支持数据格式多、操作效率高……异常强势!
毕竟是外国的东西,会有那么一点水土不服,那就是编码问题。强大的开源的组件好像都有这个毛病,仔细想想python、sqlite、qt、qgis、gdal……
问题描述
使用C#+GDAL访问中英文路径的shp和gdb都不存在问题,可打开中文路径的mdb直接报错。System.ApplicationException:"Unable to initialize ODBC connection to DSN for DRIVER=Microsoft Access Driver(*.mdb);DBQ=….."
显示是乱码了,搜遍网络,几乎没有人提出过打开mdb有异常,更别说解决方案;关于乱码,要么说C++,要么讲shp。转载的文章总是千篇一律,有用的方法万里难挑一。只有李民录大佬认真分析过,可他给的转换编码方案也不适用。绝大多数给的方案是,添加如下代码:
方案一
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
方案二
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
由于GDAL版本众多,方案一和方案二的设置都是冲突的,我也是醉了,对1.9、2.2、2.4版本的GDAL都无法解决mdb中文路径问题。
问题分析
分析1:类库版本比较
花光了CSDN上所有的积分,下载所谓解决了中文路径问题多个版本,问题依旧。
分析2:数据路径比较
string gdbPath1 = @"D:\Data\全国行政区划.gdb";(√)
string gdbPath2= @"D:\Data\china. gdb";(√)
string shpPath1 = @"D:\Data\全国行政区划\省.shp";(√)
string shpPath2 = @"D:\Data\china\p.shp ";(√)
string mdbPath1 = @"D:\Data\全国行政区划.mdb";(Х)
string mdbPath2 = @"D:\Data\国行政区划.mdb";(Х)
string mdbPath3 = @"D:\Data\China.mdb";(√)
测试发现,凡是带中文的mdb都不行,与字符数奇偶无关。
分析3:编码方式比较
测试比较默认编码(GBK2313)、UTF-8、UTF-16,确实可能是因为编码不同导致转换异常,我们来看源码中关键方法Open,要求输入utf8_path,然后第一句就直接将输入路径转为utf8字节,不管你输入的啥子,直接一顿猛如虎的操作,当作UTF8进行处理,这就是中文路径报错的原因。首先想到就是把含有中文的路径直接转换为utf8,但这里有一个重大bug,C#的变量路径都是ANSI编码,不存在转换问题,只能转字节的编码,不能转字符串的编码。
解决方案
即在是编码错误转换,那直接改成转换成默认编码好了。
修改前:将Ogr.StringToUtf8Bytes(utf8_path)
修改后:System.Text.Encoding.Default.GetBytes(utf8_path)
但测试后发现,gdb和shp又找不开了,真是"牛鞭不滑马鞭滑"(形容问题处理后又导致了新问题的一句土话)。理论上,mdb,gdb,shp应该是一样的问题才对,真不知里面是怎么处理的。无奈,暂时通过判断输入路径是否为mdb来判断是否修改,如下: