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

针对这个问题,今天仔细研究(查看+折腾)了下C#程序中string类型的默认编码方式。首先通过下面的代码进行检测C#程序中string类型的默认编码方式是什么。

static void Main(string[] args)
{
string s = "我"; // 首先获取默认编码的字节及其长度,并输出
byte[] bDefault =Encoding.Default.GetBytes(s);
Console.WriteLine(bDefault.Length);
foreach (byte b inbDefault)
{
Console.WriteLine(b);
} // 接下来获取Unicode编码的字节及其长度,并输出
byte[] bUnicode =Encoding.Unicode.GetBytes(s);
Console.WriteLine(bUnicode.Length);
foreach (byte b inbUnicode)
{
Console.WriteLine(b);
} // 接下来获取UTF8编码的字节及其长度,并输出
byte[] bUTF8 =Encoding.UTF8.GetBytes(s);
Console.WriteLine(bUTF8.Length);
foreach (byte b inbUTF8)
{
Console.WriteLine(b);
} // 最后获取936编码(即GB2312)的字节及其长度,并输出
byte[] b936 =Encoding.GetEncoding(936).GetBytes(s);
Console.WriteLine(b936.Length);
foreach (byte b in b936)
{
Console.WriteLine(b);
}
}

在XP64位中文操作系统与Win764位英文操作系统上运行过上面的代码片段,我们通过查看四个byte数组中的值,分别如下图所示。截图上面是十进制显示,下半部分为十六进制显示。

从上图可以清楚的看出,C#中对于汉字的默认编码应该使用的是GB2312(936)编码。这个默认的编码与操作系统也没有关系。

知道了系统默认的汉字编码方式,那么下面就来看看昨天的问题,使用代码System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path))转换后的编码到底变成了什么编码。使用下面的代码片段进行测试:

static void Main(string[] args)
{
string s = "我";
string strTEmp = System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(s));
byte[] bDefault =Encoding.Default.GetBytes(strTEmp);
Console.WriteLine(bDefault.Length);
foreach (byte b inbDefault)
{
Console.WriteLine(b);
} Console.WriteLine(strTEmp);
}

通过监视查看发现通过上面的代码转换之后的字节与UTF8前两个一致,但是第三个已经变成了ASCII码中的63即问号“?”,但是系统当前认为字符串依旧是GB2312的编码,所以字符串出现了乱码。如下图所示。

接下来我们再看看这个字符串通过swig封装之后,传入GDAL库之后的C++语言对应的字节编码是什么,使用前两篇博客中的跨语言调试方式,直接将上面的字符串“我”用Ogr.Open函数打开,然后在C++库中的文件gdal-1.10.0\port\cpl_vsil_win32.cpp中的函数VSIVirtualHandle*VSIWin32FilesystemHandler::Open( const char *pszFilename,   const char *pszAccess )处添加断点来查看传入的字符串,如下图所示:

转换前后的字符串及其字节码如下:

通过对比这个图与上面C#的字节码,发现了一个问题。C#中的bDefault字节码是(230、136、63)转换为16进制为(0xe6、0x88、0x3f)与C++库中传入的字节码一致(pszFilename)。这也就是说,通过swig封装并传入C++库后,编码保持不变,依旧是那个错误的编码。也就是说通过代码System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path))进行转换造成了编码错误,那么只需要修改这里,不让他进行转码或者在将Default改成UTF8应该就行了。

按照这个思路,将swig\csharp目录下的所有的System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path))都改成System.Text.Encoding. UTF8.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path))进行测试。

共需改动的文件不多,共有四个文件,如下图所示:

修改时,使用批量替换即可。修改完重新编译GDAL的C#库,然后将编译好的八个dll重新加入工程中,按照上面的步骤再次进行调试。进入C++的代码中,监视编码转换前后的值的变化。如下图所示。

从上图可以看出,这里传入的字符串pszFilename的编码已经变成了(0xce、0xd2),这个编码就是C#里面的默认编码或者GB2312编码,也就不是UTF8编码了。那么我们就可以通过设置GDAL_FILENAME_IS_UTF8=NO来进行读取了。

接下来,我们使用一个原来不能打开的路径,然后将GDAL_FILENAME_IS_UTF8设置为NO,进行测试。调试代码如下图所示,从图中可以看出,原来不能打开的shp已经正常打开。

控制台输出的信息为:

经过测试,这样修改可以支持所有的中文及其英文路径了。测试环境为Xp64位中文操作系统与Win764位英文操作系统。

我已经将修改后的C#版本的8个dll打包上传至CSDN资源和qq群共享,直接替换之前GDAL110版本里面的原来的dll即可。CSDN下载地址为:http://download.csdn.net/detail/liminlu0314/5809463

浅析GDAL库C#版本支持中文路径问题(续)的更多相关文章

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

    GDAL库对于C#的支持问题还是蛮多的,对于中文路径的支持就是其中之一(另一个就是通过OGR库获取图形的坐标信息). 关于C#支持中文路径,看过我之前博客的应该都不陌生,如果使用的是我修改过的GDAL ...

  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. BDD敏捷开发入门与实战

    BDD敏捷开发入门与实战 1.BDD的来由 2003年,Dan North首先提出了BDD的概念,并在随后开发出了JBehave框架.在Dan North博客上介绍BDD的文章中,说到了BDD的想法是 ...

  2. Openstack: aborted: Block Device Mapping is Invalid

    Issue: When you create an instance, you may encounter following exception: aborted: Block Device Map ...

  3. Git 直接推送到生产服务器

    假设路径为/project/path/ 设定git仓库可以直接被远程推送(需要较新的git版本,比如2.7) cd /project/path git config receive.denyCurre ...

  4. hbase大规模数据写入的优化历程

    业务背景:由于需要将ngix日志过滤出来的1亿+条用户行为记录存入Hbase数据库,以此根据一定的条件来提供近实时查询,比如根据用户id及一定的时间段等条件来过滤符合要求的若干行为记录,满足这一场景的 ...

  5. springMVC源码分析--异常处理机制HandlerExceptionResolver执行原理(二)

    上一篇博客springMVC源码分析--异常处理机制HandlerExceptionResolver简单示例(一)中我们简单地实现了一个异常处理实例,接下来我们要介绍一下HandlerExceptio ...

  6. 针对于Python的OpenCV环境搭建

    OpenCV 依赖 下载OpenCV 配置 总结 给Python搭建opencv的环境还真是略嫌麻烦,于是做下笔记,以备不时之需. OpenCV 依赖 opencv有些依赖,我们必须安装一下,否则接下 ...

  7. EXT JS认识EXTJS,第一个EXTJS例子

    大部分内容转载自:http://blog.csdn.net/wanghuan203/article/details/8011112 和http://www.cnblogs.com/willick/p/ ...

  8. 指令汇B新闻客户端开发(三) 下拉刷新

    现在我们继续这个新闻客户端的开发,今天分享的是下拉刷新的实现,我们都知道下拉刷新是一个应用很常见也很实用的功能.我这个应用是通过拉ListView来实现刷新的,先看一张刷新的原理图 从图中可知,手指移 ...

  9. iOS9中如何在日历App中创建一个任意时间之前开始的提醒(三)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 四.创建任意时间之前开始的提醒 现在我们找到了指定源中的指定日 ...

  10. TCP连接建立系列 — 客户端接收SYNACK和发送ACK

    主要内容:客户端接收SYNACK.发送ACK,完成连接的建立. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 接收入口 tcp_v4_rcv |--&g ...