最近在研究GDAL,在嘗試將矢量數據導入到pg中時出現了中文字段亂碼的問題。亂碼類似於下圖:
百度了一下,大部分都是說要設置
Gdal.SetConfigOption("SHAPE_ENCODING", string.Empty);
但是我設置完之後完全沒用,甚至還不如之前,一個漢字都沒了全變成亂碼了。我有跟斷點發現我從源數據裏讀出來的數據就已經是亂碼了,感覺有點拉閘。最後在一個羣友的指導下,通過DllImport的方式引用原本的gdal204.dll(不同的GDAL版本數字不同)文件,使用裏面的字段讀取函數來獲取字段的值。雖然一開始也是亂碼,但是上面的編碼設置終於起作用了,加上後終於正常了。個人推測是GDAL的C#編譯版在讀取中文字段的時候有問題,但是具體什麼原因我也沒搞明白。具體代碼如下。
[DllImport("gdal204.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr OGR_F_GetFieldAsString(HandleRef handle, int fieldIdx);
private static void ImportVectorData2PG()
{
Ogr.RegisterAll();
// 支持中文路徑
// Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
// 使字段支持中文
Gdal.SetConfigOption("SHAPE_ENCODING", string.Empty);
// 讀取矢量文件信息
string sourceVector = @"D:\DTLFolder\ogrtest.shp";
DataSource srcVectorDs = Ogr.Open(sourceVector, 0);
// 只讀取第一個圖層
Layer srcVectorLy = srcVectorDs.GetLayerByIndex(0);
FeatureDefn srcVectorDefn = srcVectorLy.GetLayerDefn();
string layerName = srcVectorLy.GetName();
SpatialReference spatialReference = srcVectorLy.GetSpatialRef();
wkbGeometryType wkbGeometryType = srcVectorLy.GetGeomType();
// 讀取PG庫信息
string connStr = "PG:dbname=yanshi host=localhost port=5432 user=postgres password=postgres";
OSGeo.OGR.Driver drv = Ogr.GetDriverByName("PostgreSQL");
DataSource dataSource = drv.Open(connStr, 1); // 0是隻讀?
Layer layer = dataSource.GetLayerByName(layerName);
// 沒有同名圖層則創建同結構新圖層
if (layer == null)
{
layer = dataSource.CreateLayer(layerName, spatialReference, wkbGeometryType, null);
int fieldCount = srcVectorDefn.GetFieldCount();
for (int i = 0; i < fieldCount; i++)
{
FieldDefn fieldDefn = srcVectorDefn.GetFieldDefn(i);
layer.CreateField(fieldDefn, 1);
}
int geoFieldCount = srcVectorDefn.GetGeomFieldCount();
for (int i = 0; i < geoFieldCount; i++)
{
GeomFieldDefn geomFieldDefn = srcVectorDefn.GetGeomFieldDefn(i);
layer.CreateGeomField(geomFieldDefn, 1);
}
}
// 循環賦值創建
Feature feature = null;
while ((feature = srcVectorLy.GetNextFeature()) != null)
{
FeatureDefn featureDefn = layer.GetLayerDefn();
Feature newFeature = new Feature(featureDefn);
for (int i = 0; i < srcVectorDefn.GetFieldCount(); i++)
{
FieldDefn oDefn = srcVectorDefn.GetFieldDefn(i);
FieldType type = oDefn.GetFieldType();
switch (type)
{
case FieldType.OFTInteger:
newFeature.SetField(i, feature.GetFieldAsInteger(i));
break;
case FieldType.OFTReal:
newFeature.SetField(i, feature.GetFieldAsDouble(i));
break;
case FieldType.OFTString:
string val = Marshal.PtrToStringAnsi(OGR_F_GetFieldAsString(Feature.getCPtr(feature), i));
newFeature.SetField(i, val);
break;
default:
newFeature.SetField(i, feature.GetFieldAsString(i));
break;
}
}
for (int i = 0; i < srcVectorDefn.GetGeomFieldCount(); i++)
{
Geometry geometry = feature.GetGeomFieldRef(i);
newFeature.SetGeometry(geometry);
}
layer.CreateFeature(newFeature);
}
}