C# GDAL編碼問題2——讀取中文屬性


前面解決了打開mdb亂碼的問題,但又出現讀取中文屬性亂碼的問題,不光是mdb,還有gdb,shp都存在此問題,究其原因依然是封裝C#版時的bug造成的,直接說解決方案:

原版有個Utf8BytesToString方法,直接調用PtrToStringAnsi獲取字節長度,沒有考慮不同編碼字節長度不同的問題。

修改前:

修改后:

internal static string Utf8BytesToString(IntPtr pNativeData)
{
    string result;
    if (pNativeData == IntPtr.Zero)
    {
        result = null;
    }
    else
    {
        int num = 0;
        byte[] array = new byte[0];
        do
        {
            num++;
            Array.Resize<byte>(ref array, num);
            Marshal.Copy(pNativeData, array, 0, num);
        }
        while (array[num - 1] != 0);
        if (1 == num)
        {
            result = "";
        }
        else
        {
            Array.Resize<byte>(ref array, num - 1);
            result = Encoding.UTF8.GetString(array);
        }
    }
    return result;
}

同樣的問題在於SWIGStringHelper類中CreateString方法。

修改前:

修改后:

protected class SWIGStringHelper
{
	[DllImport("ogr_wrap")]
	public static extern void SWIGRegisterStringCallback_Ogr(OgrPINVOKE.SWIGStringHelper.SWIGStringDelegate stringDelegate);

	private static string CreateString(IntPtr pNativeData)
	{
		string result;
		if (pNativeData == IntPtr.Zero)
		{
			result = null;
		}
		else
		{
			int num = 0;
			byte[] array = new byte[0];
			do
			{
				num++;
				Array.Resize<byte>(ref array, num);
				Marshal.Copy(pNativeData, array, 0, num);
			}
			while (array[num - 1] != 0);
			if (1 == num)
			{
				result = "";
			}
			else
			{
				Array.Resize<byte>(ref array, num - 1);
				result = Encoding.UTF8.GetString(array);
			}
		}
		return result;
	}

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

	private static OgrPINVOKE.SWIGStringHelper.SWIGStringDelegate stringDelegate = new OgrPINVOKE.SWIGStringHelper.SWIGStringDelegate(OgrPINVOKE.SWIGStringHelper.CreateString);

	public delegate string SWIGStringDelegate(IntPtr pNativeData);
}

但這樣的修改還是只能處理gdb和shp問題,mdb的還是不行!得調用底層GDAL的API才行。

選來一個擴展方法:

/// <summary>
/// 讀取要素字段值
/// </summary>
/// <param name="handle"></param>
/// <param name="index"></param>
/// <returns></returns>
[DllImport("gdal204.dll", EntryPoint = "OGR_F_GetFieldAsString", CallingConvention = CallingConvention.Cdecl)]
public static extern System.IntPtr OGR_F_GetFieldAsString(HandleRef handle, int index);

/// <summary>
/// 讀取要素字段值
/// </summary>
/// <param name="feature"></param>
/// <param name="index"></param>
/// <returns></returns>
public static string GetFieldAsStringEx(this Feature feature, int index)
{
    IntPtr pStr = OGR_F_GetFieldAsString(Feature.getCPtr(feature), index);
    return Marshal.PtrToStringAnsi(pStr);
}
public static string GetFieldAsStringEx(this Feature feature, string name)
{
    var index = feature.GetFieldIndex(name);
    if (index >= 0)
    {
        return (GetFieldAsStringEx(feature, index));
    }

    throw new IndexOutOfRangeException();
}

再使用擴展方法來讀取就好了。

Layer layer = mdbDataSource.GetLayerByIndex(1);

FeatureDefn featureDefn = layer.GetLayerDefn();
int iFieldCount = featureDefn.GetFieldCount();
Feature feature = null;
while ((feature = layer.GetNextFeature()) != null)
{
    string s = "";
    for (int j = 0; j < iFieldCount; j++)
    {
        s += feature.GetFieldAsStringEx(j) + "\t\t\t";
    }
    Console.WriteLine(s);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM