1. 程式人生 > >GDAL C#中文路徑,中文屬性名稱亂碼問題

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的就沒有這個問題。