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