> ## Content Index
> Fetch the complete content index at: https://blog.anthea.day/llms.txt
> Use this file to discover other available public pages before exploring further.

# 歡迎來到 GIS 的世界－ Day 14：NetTopologySuite 的讀取和建立
- URL: https://blog.anthea.day/series-2022-ithome-14/
- Published: 2022-09-27T16:01:43.000Z
- Updated: 2026-11-06T19:10:56.000Z
- Author: Anthea / 芫荽
- Tags: #Migrated-1792241843742, #Import 2026-10-17 12:57, Coding, 2022 iThome 鐵人賽：歡迎來到 GIS 的世界

將 `NetTopologySuite.IO.Esri` 加入我們的專案之後，就可以開始對我們的 Shapefile 進行操作了。這裡使用[政府開放平臺](https://data.gov.tw/dataset/7441?ref=blog.anthea.day)所提供的資料作為範例，也是我們之後實作會使用到的其中一個檔案。

```C#
using NetTopologySuite.IO.Esri;

foreach (var feature in Shapefile.ReadAllFeatures(@"shapefile path"))
{
    foreach (var attrName in feature.Attributes.GetNames())
    {
        Console.WriteLine($"{attrName,10}: {feature.Attributes[attrName]}");
    }
    
    // Console.WriteLine($"     SHAPE: {feature.Geometry.AsText()}");
    Console.WriteLine($"      SRID: {feature.Geometry.SRID}");
    Console.WriteLine();
}
```

### 讀取

根據 GitHub 上的寫法，只要簡單的這幾行，馬上就能讀取 Shapefile 了！執行後的結果如下：

![](https://cdn-images-1.medium.com/max/800/0*Euiv22Yohm8FR5Zj.png)

從讀取後的結果可以看到，之前讓我們在 GDAL 中痛苦不已的中文，在 `NetTopologySuite` 上可以好好的正常顯示！（痛哭流涕）

另外也可以看到，`NetTopologySuite` 在寫法上相對來說更為簡潔，一開始可以選擇直接讀取 `Feature` 就好，再透過欄位名稱從 `Atrributes` 取得 `Field` 的值，不像 GDAL 還需要從 `Layer` 先取得 `Layer` 的數量跑回圈，接著從 `Layer` 拿 `layer.GetNextFeature()` 才能開始讀資料，可讀性比起 GDAL 高出許多。

### 輸出

```C#
using System.Text;
using NetTopologySuite.Features;
using NetTopologySuite.IO;
using NetTopologySuite.IO.Esri;

var features = new List<Feature>();
var wktReader = new WKTReader();
var fcuGeometry = wktReader.Read(
    "POLYGON((214094.18733422138 2675204.397772933,214613.04806256315 2675203.096234374,214612.0331897791 2674795.5200602347,214093.15758024747 2674796.8214499434,214094.18733422138 2675204.397772933))");

var fcuAttributes = new AttributesTable();
fcuAttributes.Add("日期", DateTime.Today);
fcuAttributes.Add("地點", "逢甲大學");
var fcuFeature = new Feature(fcuGeometry, fcuAttributes);
features.Add(fcuFeature);

var nightMarketGeometry = wktReader.Read(
    "POLYGON((213945.3342767608 2674876.347737663,214097.93845940504 2674873.793433358,214099.4943339883 2674626.6362772766,214474.48457545802 2674625.694102451,214511.39058478415 2674562.7289472898,214223.11502519806 2674368.326804782,213983.77470059253 2674559.719947559,213945.3342767608 2674876.347737663))");
var nightMarketAttributes = new AttributesTable();
nightMarketAttributes.Add("日期", DateTime.Today);
nightMarketAttributes.Add("地點", "逢甲夜市");
var nightMarketFeature = new Feature(nightMarketGeometry, nightMarketAttributes);
features.Add(nightMarketFeature);

Shapefile.WriteAllFeatures(features, @"files\create.shp", Encoding.UTF8);
```

根據 GitHub 上的範例，一樣可以簡單的利用使用 `Shapefile.WriteAllFeatures()` 來建立。不過，範例上建立的是 `MultiLine` ，把他修改成 `Polygon` 之後，執行時遇到了一個錯誤：

![](https://cdn-images-1.medium.com/max/800/0*9B6SgVvJJqPDBCaL.png)

#### 這個 Exception 哪裡來

一開始看到錯誤原因的時候真的覺得很茫然 ? 我很確定我的 WKT 是 Polygon 沒有錯，為甚麼 Exception 會告訴我我想把 Polygon 轉換成 Multi Polygon 呢 ?

於是開啟 debbug mode，順著程式碼一行一行往下找，終於在 `Shapefile.cs` 中找到一點線索。在最後要使用 Writer 寫入的時候，他所建立的 Writer 泛型所吃的類別竟然只有 `Multi Polygon` 的選項 ?

也就是說，就算我的 Geometry 型別是 `Polygon` ，但 Writer 依舊會以 `MultiPolygon` 建立，但因為型別不同，所以在使用 Writer 前他會一直想把我的型別轉換成 `MultiPolygon` ，才會一直噴出 Exception。

但原始碼裡，Writer 只有針對 `MultiPolygon` 去進行寫入的方法，也就等於所有 Polygon 相關的類別：`Polygon`、`PolygonM`、`PolygonZ`、`PolygonZM` 都會使用 Multi Polygon Writer 去建立。

#### References

- [NetTopologySuite.IO.Esri 官方 GitHub](https://ithelp.ithome.com.tw/articles/10293033/draft?ref=blog.anthea.day)