浅析GDAL库C#版本支持中文路径问题
GDAL库对于C#的支持问题还是蛮多的,对于中文路径的支持就是其中之一(另一个就是通过OGR库获取图形的坐标信息)。
关于C#支持中文路径,看过我之前博客的应该都不陌生,如果使用的是我修改过的GDAL库,可以通过设置下面的代码即可让C#直接支持中文路径。如果使用官方的库,不用设置直接应该就可以支持中文路径。
// 注册所有的驱动
Ogr.RegisterAll(); // 为了支持中文路径,请添加下面这句代码
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","YES");
// 为了支持shp属性表字段支持中文,请添加下面这句
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING","");
昨天,一位朋友说,他测试C#版本,发现中文路径有时候可以,有时候不可以,通过设置GDAL_FILENAME_IS_UTF8也无济于事。
今天通过测试发现,只要是文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,肯定不能读取和创建。
比如下面的文件名就是正常的:
D:\\新建文件夹\\新建1.shp
D:\\密云数据\\线分离的0.shp
而下面的肯定就是不行:
D:\\新建文件夹\\新建的1.shp
D:\\密云数据\\线分离0.shp
下面就通过C#程序调试GDAL库,找找原因。按照上篇博客中的跨语言调试的方式,在C#程序中的Open函数处设置断点,然后启动调试,程序在此处中断。
首先用一个GDAL库可以打开的正常路径进行测试,如下图所示。
接下来按F11键,进入swig封装的C#代码中,如下图所示。
在这里,我们发现了这样的代码。
public static DataSourceOpen(string utf8_path, int update) {
IntPtr cPtr =OgrPINVOKE.Open(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)),update);
DataSource ret = (cPtr ==IntPtr.Zero) ? null : new DataSource(cPtr, true, ThisOwn_true());
if(OgrPINVOKE.SWIGPendingException.Pending) throwOgrPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
其中在调用OgrPINVOKE时,将路径进行了编码转换,核心代码如下:
System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path))
从代码可以看出,Swig首先将C#默认的字符串,使用UTF8的编码转换为默认的编码。上面的路径“D:\新建文件夹\新建1.shp”通过这句转换之后就变成了“D:\鏂板缓鏂囦欢澶筡鏂板缓1.shp”。而这个字符串传入GDAL库后,在文件gdal-1.10.0\port\cpl_vsil_win32.cpp中的函数VSIVirtualHandle*VSIWin32FilesystemHandler::Open( const char *pszFilename, const char *pszAccess )中又进行了一次编码转换。如下图所示。
通过上图,可以发现,如果设置了GDAL_FILENAME_IS_UTF8=YES时,系统先将编码从UTF8转为UCS2编码。通过这句之后,发现路径又编程了原来的,如下图:
这样GDAL库就可以正常打开该文件。下面再看一个GDAL不能打开的路径重复上面的步骤,下面只截取关键位置的截图。
首先是在打开时设置断点,文件路径为“D:\新建文件夹\新建的1.shp”
然后传入GDAL库中的路径通过转码变成了“D:\鏂板缓鏂囦欢澶筡鏂板缓鐨?.shp”。之后再通过GDAL库中的函数转为宽字节时称为了“D:\新建文件夹\新建çš?.shp”。如下图所示。
只要路径中出现了问号(?),这个路径肯定有问题,不管是不是乱码。所以这个路径肯定就打不开了。
通过上面的步骤,我们可以确定,C#的路径是好使的,而通过SWIG中的编码转换后就出现了问题,所以我们可以认为是编码转换出现的问题。
在SWIG封装的接口中,使用System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path))进行转换,下面针对此代码片段写一个简单的测试代码进行验证。
staticvoid Main(string[] args)
{
string strUtf8 = "D:\\新建文件夹\\新建的1.shp"; byte[] byutf8 =System.Text.Encoding.UTF8.GetBytes(strUtf8);
string strDefault =System.Text.Encoding.Default.GetString(byutf8); byte[] byDefault =System.Text.Encoding.Default.GetBytes(strDefault);
string strUtf8n = System.Text.Encoding.UTF8.GetString(byDefault);
}
首先看一个GDAL可以正常访问的路径,首先查看转换后再转回来,共三个字符串的对比,如下图,从图中可以看出,转换为Default再转为utf8之后,与原来的路径一样。所以GDAL库可以正常访问。
而转换前后获取的byte数组内容完全一致,如下图所示:
下面再使用一个GDAL不能访问的路径进行测试,查看转换后再转回来,共三个字符串的对比,如下图,从图中可以看出,转换为Default再转为utf8之后,与原来的路径发生了变化。
下面比较两次转换的byte数组,按理说内存中的byte数组应该是一样的,下面对比两个byte数组中的内容,如下图所示,从图中可以发现,数组转换前的27和28分别是132和49,而转换后,这两个字节变成了一个字节(63)。
从这里可以看出,可以认为问题就出在此处。对应ASCII码表,将上图中的值转为字符串,可以得到下面的图。英文字符占用一个byte,而汉字占用3个byte。而在转码的时候应该是两个字节为一组进行转码处理,也就是说对于偶数个汉字,转成byte是3倍的偶数,结果肯定是偶数,所以按照两个字节转码刚好可以转完;而汉字为奇数个,转成byte是3倍的奇数,结果肯定是个奇数,按照两个字节转码,肯定会多出来一个,这多出来的一个系统可能不认识就用问号(?)来表示了。
所以,可以这么认为,汉字是偶数的就正常,奇数的就会出现问题,与GDAL表现的结果完全一致。上面的最后这一段的是我个人的分析,不代表微软内部就是这么实现的。或许这可能算作C#的一个bug?不知道微软有没有发现这个问题。
浅析GDAL库C#版本支持中文路径问题的更多相关文章
- 浅析GDAL库C#版本支持中文路径问题(续)
上篇博客中主要说了GDAL库C#版本中存在的问题,其表现形式主要是:"文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,读取和创建都会报错." ...
- GDAL支持中文路径和Shp文件中文属性写入
在使用GDAL的过程中,为了支持中文,比需手动进行中文路径的设置,同时特别是在对Shp的属性进行中文输入的时候,都必须进行必要的设定. 为了支持中文路径,在注册了驱动之后,加上第三句就可以了.必须设置 ...
- svn不支持中文路径问题的解决
作者:朱金灿 来源:http://blog.csdn.net/clever101 svn的授权文件authz默认是不支持中文路径的,因此在精确控制中文文件夹的授权时往往会出错.要解决这个问题,需要用U ...
- 使GDAL库支持中文路径或中文文件名的处理方法
之前生成的gdal 2.1.1动态库,在通过命令行执行时,遇到有中文路径或中文图像名时,GDALOpen函数不能正确的被调用,如下图: 解决方法: 1. 在所有使用GDALAllRegist ...
- 解决tomcat不支持中文路径的问题
问题描述: 开发文件下载功能时,因为需求比较简单,要求下载一个说明文件.于是,直接给出了文件所在服务器的地址,通过链接直接下载此文件(因需求简单,未考虑安全方面的问题-_-||). 在这个过程中,文件 ...
- 【转】让apache支持中文路径或者中文文件
本帖最后由 狂人阿川 于 2013-4-12 19:13 编辑 今天在给一美国VPS客户调试他的程序的时候.发现他的网站有中文名称.貌似apache无法认识中文路径,火狐下面能下载他的文件,IE下面不 ...
- Unity3D 原来Unity比较新的版本支持中文
注意: Unity 2018.2 以上版本才可以
- Jenkins的FTP上传插件Publish Over FTP Plugin设置支持中文路径
[系统管理]->[系统设置]->[Publish over FTP]->[Control encoding]->输入[GB2312]或者[UTF-8]
- ImageMaigck不支持中文路径的问题
不知道咋回事. 回顾下: char* pTest1 = "测试.txt"; wchar_t* pTest2 = L"测试.txt"; 以上是pTest1指向的内 ...
随机推荐
- Swift基础之实现选择图片时,出现类似于ActionSheet的样式
之前看到过有APP在选择图片时,调用手机相册时,将手机相册做成了左右滑动选择的效果,这次展示的就是这种样式,用OC语言已经有人实现过类似的代码,在这里写的仅仅是效果展示的代码调用,具体代码,可以自己研 ...
- 拾遗与填坑《深度探索C++对象模型》3.2节
<深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...
- 全面剖析Redis Cluster原理和应用
全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最 ...
- 使用Linux脚本更新Weblogic部署的应用程序
在利用Jenkins实现Weblogic应用自动部署的功能时,如何通过Shell 脚本自动更新Weblogic部署的应用程序呢? 可以使用weblogic.jar包中的weblogic.Deploye ...
- 解决linux删除文件后空间没有释放问题
linux删除文件后沒有释放空间 今天发现一台服务器的home空间满了,于是要清空没用的文件,当我删除文件后,发现可用空间沒有变化 os:centos4.7 现象: 发现当前磁盘空间使用情况: [ro ...
- SQL Join各种内联外联说明
Visual Representation of SQL Joins C.L. Moffatt, 3 Feb 2009 CPOL 4.96 (406 votes) Rate this: This ...
- Linux 高性能服务器编程——I/O复用的高级应用
高级应用一:非阻塞connect connect系统调用的man手册中有如下的一段内容: EINPROGRESS The socket is non-blocking and the connecti ...
- cassandra 监控方案评估
摘要 最开始做cassandra monitor 方案的选型时,主要是从cassandra 本身入手,后来发现cassandra运行在JVM上,所有的metrics都是通过JMX 暴露出来.所以又可以 ...
- maven项目管理
systemPath方式 有些不通用的包,maven仓库没有,只能通过本地包依赖,就像下面方式: 在需要依赖的项目建lib文件夹,如下: 然后在pom.xml项目管理文件里面加入本地依赖,如下 这种情 ...
- Hive-RCFile文件存储格式
在新建Hive表时,可以使用stored as rcfile来指定hive文件的存储方式为RCFile. 一.RCFile文件结构 下图是一个RCFile的文件结构形式. 从上图可以看出: 1)一张表 ...