GDAL讀取S-57海圖資料中文屬性值亂碼問題解決(續)

來源:互聯網
上載者:User

上篇博文中的代碼使用了函數wcstombs來進行處理,今天發現GDAL庫裡面提供了寬位元組轉單位元組的函數,名字叫CPLRecodeFromWChar(這個函數需要libiconv庫的支援,也就是在編譯GDAL的時候需要把libiconv庫一起編譯)。本以為C#語言也可以使用,結果很悲劇的發現,C#的提供的介面中沒有相關的函數,看來使用C#的同學有點悲劇了。

需要說明的是,需要先用函數CPLRecodeFromWChar將寬位元組轉為UTF8,然後再使用函數CPLRecode將UTF8轉為漢字編碼(CP936)。

程式依舊是昨天的那個,函數全部換成GDAL的函數,代碼如下:

int ReadS57()  {  CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");  OGRRegisterAll();  //開啟資料  const char* pszS57 = "D:\\C1100102.000";  OGRDataSource *poDS = OGRSFDriverRegistrar::Open(pszS57, FALSE );  if( poDS == NULL )  {  printf( "Open failed.\n" );  return 1;  }  // 擷取有中文屬性值的圖層  OGRLayer *poLayer = poDS->GetLayerByName( "BUAARE" );  if( poLayer == NULL )  {  printf( "Get Layer failed.\n" );  OGRDataSource::DestroyDataSource( poDS );  return 1;  }  poLayer->ResetReading();  OGRFeature *poFeature = poLayer->GetNextFeature();  while (poFeature != NULL )  {  OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();   //擷取屬性欄位值  // 為了示範說明,就只輸出亂碼的屬性值 const char* pszAttValue = poFeature->GetFieldAsString("NOBJNM"); size_t size = strlen(pszAttValue);if (size != 0){char* pszValue = new char[size];memcpy(pszValue, pszAttValue, size);pszValue[size-1] = '\0';char *pszGetUTF8 = CPLRecodeFromWChar( (const wchar_t*)pszValue, CPL_ENC_UCS2, CPL_ENC_UTF8);pszAttValue = CPLRecode( pszGetUTF8, CPL_ENC_UTF8, "");delete []pszValue;}printf("%s\n", pszAttValue); OGRFeature::DestroyFeature( poFeature );  poFeature = poLayer->GetNextFeature();  }  OGRDataSource::DestroyDataSource( poDS );  return 0;  }

是執行輸出的結果,和使用QGIS開啟對比。

通過上面的方式是可以解決這個問題,不過稍微有點麻煩,需要在每次擷取屬性值的時候都要進行判斷。我們可以直接修改GDAL庫中的代碼,這樣在讀取的時候直接就是漢字編碼。找了一下午,在GDAL庫的源碼中檔案gdal-1.9.2\ogr\ogrsf_frmts\s57\s57reader.cpp行883左右,修改為下面:

// Add By liml 2013-04-25 Convert UCS-2 to Utf-8const char* pachBuffer = poRecord->GetStringSubfield("NATF",0,"ATVL",iAttr);if( EQUAL(pszAcronym, "NOBJNM")){size_t nLength = strlen(pachBuffer);char* pszValue = new char[nLength];memcpy(pszValue, pachBuffer, nLength);pszValue[nLength-1] = '\0';char *pszGetUTF8 = CPLRecodeFromWChar( (const wchar_t*)pszValue, CPL_ENC_UCS2, CPL_ENC_UTF8);pachBuffer = CPLRecode( pszGetUTF8, CPL_ENC_UTF8, CPL_ENC_LOCALE);delete []pszValue;}// Add By liml 2013-04-25        poFeature->SetField( pszAcronym, pachBuffer);

下面是使用ogrinfo輸出的對比情況,左邊是沒修改時輸出的,右邊是修改後輸出的。

雖然這麼修改是可以解決這個問題,但是不知道會不會引起其他的副作用。等發現了再修改吧。修改之後的GDAL庫已經上傳至我的資源中心,有需要的同學可以自行去下載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.