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#版本支持中文路径问题的更多相关文章

  1. 浅析GDAL库C#版本支持中文路径问题(续)

    上篇博客中主要说了GDAL库C#版本中存在的问题,其表现形式主要是:"文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,读取和创建都会报错." ...

  2. GDAL支持中文路径和Shp文件中文属性写入

    在使用GDAL的过程中,为了支持中文,比需手动进行中文路径的设置,同时特别是在对Shp的属性进行中文输入的时候,都必须进行必要的设定. 为了支持中文路径,在注册了驱动之后,加上第三句就可以了.必须设置 ...

  3. svn不支持中文路径问题的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 svn的授权文件authz默认是不支持中文路径的,因此在精确控制中文文件夹的授权时往往会出错.要解决这个问题,需要用U ...

  4. 使GDAL库支持中文路径或中文文件名的处理方法

    之前生成的gdal 2.1.1动态库,在通过命令行执行时,遇到有中文路径或中文图像名时,GDALOpen函数不能正确的被调用,如下图: 解决方法: 1.      在所有使用GDALAllRegist ...

  5. 解决tomcat不支持中文路径的问题

    问题描述: 开发文件下载功能时,因为需求比较简单,要求下载一个说明文件.于是,直接给出了文件所在服务器的地址,通过链接直接下载此文件(因需求简单,未考虑安全方面的问题-_-||). 在这个过程中,文件 ...

  6. 【转】让apache支持中文路径或者中文文件

    本帖最后由 狂人阿川 于 2013-4-12 19:13 编辑 今天在给一美国VPS客户调试他的程序的时候.发现他的网站有中文名称.貌似apache无法认识中文路径,火狐下面能下载他的文件,IE下面不 ...

  7. Unity3D 原来Unity比较新的版本支持中文

    注意: Unity 2018.2 以上版本才可以

  8. Jenkins的FTP上传插件Publish Over FTP Plugin设置支持中文路径

    [系统管理]->[系统设置]->[Publish over FTP]->[Control encoding]->输入[GB2312]或者[UTF-8]

  9. ImageMaigck不支持中文路径的问题

    不知道咋回事. 回顾下: char* pTest1 = "测试.txt"; wchar_t* pTest2 = L"测试.txt"; 以上是pTest1指向的内 ...

随机推荐

  1. 硬盘存储计量单位KB、MB、GB大小换算

    一. 预备知识 1. bit与byte 1. bit(简记为 b) 1 bit = 0 or 1 = one binary 2. byte(简记为 B) 1 byte = 8 bits 1字节,8个二 ...

  2. RX系列四 | RxAndroid | 加载图片 | 提交表单

    RX系列四 | RxAndroid | 加载图片 | 提交表单 说实话,学RxJava就是为了我们在Android中运用的更加顺手一点,也就是RxAndroid,我们还是先一步步来,学会怎么去用的比较 ...

  3. 使用Spring Boot开发Web项目

    前面两篇博客中我们简单介绍了Spring Boot项目的创建.并且也带小伙伴们来DIY了一个Spring Boot自动配置功能,那么这些东西说到底最终还是要回归到Web上才能体现出它的更大的价值,so ...

  4. iOS 应用打包命令一览

    文章转载自:http://www.jianshu.com/p/5d59966eaecc 文章排版部分根据自己的理解做了一些修改. 各种命令的简介 使用命令打包iOS 应用一般会用到 xcodebuli ...

  5. springMVC源码分析--ControllerClassNameHandlerMapping(九)

    在上一篇博客springMVC源码分析--AbstractControllerUrlHandlerMapping(六)中我们介绍到AbstractControllerUrlHandlerMapping ...

  6. 【BAT经典算法面试题系列】求和为n的连续正整数

    马上就要到9月份了,意味着一年一度的秋招就要开始了,相信不论是正在实习的童鞋还是马上就要找工作的童鞋,BAT无疑是国内的"明星企业",是每个学计算机的小伙伴们心之向往的企业,但是呢 ...

  7. AR模块常用函数

    --AR模块常用函数 FUNCTION get_fnd_user_name ( p_user_id IN NUMBER ) return VARCHAR2 IS CURSOR c_user_name ...

  8. JQuery 网页选项卡制作

    网页选项卡可以较好的利用有限的页面来展示更多的元素,而使用JQuery来制作网页选项卡也是一件非常简单的事情.今天就来分享一个网页选项卡的制作小技巧. 引入所需库 选项卡原理 业务核心 完整小例子 引 ...

  9. java详解final、多态、抽象类、接口原理

    1:final关键字(掌握) (1)是最终的意思,可以修饰类,方法,变量. (2)特点: A:它修饰的类,不能被继承. B:它修饰的方法,不能被重写. C:它修饰的变量,是一个常量. (3)面试相关: ...

  10. 深入理解Express.js

    转自:http://xvfeng.me/posts/understanding-expressjs/ 英文原文更赞:http://evanhahn.com/understanding-express- ...