GDAL C#中文路径,中文属性名称乱码问题

昨天写的博客,将C#读取shp中文属性值乱码的问题应该可以解决,博客地址为:http://blog.csdn.net/liminlu0314/article/details/54096119,然后又测试发现中文路径,中文属性值如果有中文时,也会出现乱码,具体表现为偶数个汉字没有问题,奇数个汉字会出现乱码。
继续调试C#的源码,发现问题还是在于将C++库中返回的结果进行编码转换的时候导致的,源码位于OgrPINVOKE.cs文件中。截取原始的代码如下:

  protected class SWIGStringHelper {

    public delegate string SWIGStringDelegate(string message);
    static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString);

    [DllImport("ogr_wrap", EntryPoint="SWIGRegisterStringCallback_Ogr")]
    public static extern void SWIGRegisterStringCallback_Ogr(SWIGStringDelegate stringDelegate);

    static string CreateString(string cstring) //这个函数出问题
    {
        return cstring;
    }

    static SWIGStringHelper() {
      SWIGRegisterStringCallback_Ogr(stringDelegate);
    }
  }

出问题的函数在于CreateString,这个函数是一个类似C的回掉函数,直接将C库中返回的const char*直接转为C#中的string进行返回,这样的结果就是如果C库中的const char*以UTF8编码的话,直接返回的就是乱码,并且可能导致截断。所以就表现为图层名乱码,属性字段名乱码等问题。
解决方案与昨天处理的类似,将C库中的const char*用UTF8编码之后再返回应该就没问题了,修改后的代码如下所示:

  protected class SWIGStringHelper {

    public delegate string SWIGStringDelegate(IntPtr message);//此处修改参数类型
    static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString);

    [DllImport("ogr_wrap", EntryPoint="SWIGRegisterStringCallback_Ogr")]
    public static extern void SWIGRegisterStringCallback_Ogr(SWIGStringDelegate stringDelegate);

    static string CreateString(IntPtr pNativeData)//此处函数内容需要修改
    {
        if (pNativeData == IntPtr.Zero)
            return "";

        //下面这一长串就是获取C字符串的长度,用Marshal库中的函数获取的都有问题,所以就用下面的循环来自己找了,如果有更好的方案请告知。
        int nAnsiLength = Marshal.PtrToStringAnsi(pNativeData).Length;
        int nUniLength = Marshal.PtrToStringUni(pNativeData).Length;
        int nMaxLength = (nAnsiLength > nUniLength) ? nAnsiLength : nUniLength;
        int length = 0;
        for (int i = 0; i < nMaxLength; i++)
        {
            byte[] strbuf1 = new byte[1];
            Marshal.Copy(pNativeData + i, strbuf1, 0, 1);
            if (strbuf1[0] == 0)
            {
                break;
            }
            length++;
        }

        byte[] strbuf = new byte[length];
        Marshal.Copy(pNativeData, strbuf, 0, length);
        return System.Text.Encoding.UTF8.GetString(strbuf);
    }

    static SWIGStringHelper() {
      SWIGRegisterStringCallback_Ogr(stringDelegate);
    }
  }

修改完保存,同样的问题有4个文件,分别是OgrPINVOKE.cs、GdalPINVOKE.cs、OsrPINVOKE.cs和GdalConstPINVOKE.cs。 将这四个文件中SWIGStringHelper类中的内容都按照上面这样修改,然后重新生成dll,即可。

PS:上面的修改完之后,调试时没有问题,直接运行的时候最后一个汉字可能会丢失,问题很奇怪,不知道为啥。

编译好的库已经上传,下载地址为:http://download.csdn.net/detail/liminlu0314/9730475
PS:经过测试,发现上面丢失最后一个汉字的问题已经解决,之前是debug的版本,用release的就没有这个问题。

posted on 2017-01-06 11:06  王大王  阅读(815)  评论(0编辑  收藏  举报

导航