# Day34 Golang 操作CSV
**CVS** 是以逗號`,`及換行`\n`分隔的資料格式,
從CSV的英文(Comma-Separated Values)中就能窺出一二。
## CSV長的怎樣
用Excel開啟一個CSV檔案
(副檔名要為.csv 而非.xlsx。 xlsx是 Microsoft Office Excel 獨有的格式)

用記事本開啟一個CSV檔案
原來就長成這樣而已

(也有出現以空白字元` `、`\t` 或其他字元來做分隔,只要解析時以該字元下去做區隔就行)
## 讀取 Read CSV
Golang讀檔案時會需要用到`絕對路徑`,
在這邊先取 `pwd` 當前路徑、再加上 `fileName` 檔案名稱。
```go=
var Pwd string
var FilePath string
var FileName = "test.csv"
func init() {
Pwd, _ = os.Getwd()
FilePath = filepath.Join(Pwd, FileName)
}
func Load() {
file, err := os.OpenFile(FilePath, os.O_RDONLY, 0777) // os.O_RDONLY 表示只讀、0777 表示(owner/group/other)權限
if err != nil {
log.Fatalln("找不到CSV檔案路徑:", FilePath, err)
}
// read
r := csv.NewReader(file)
r.Comma = ',' // 以何種字元作分隔,預設為`,`。所以這裡可拿掉這行
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatalln(err)
}
var a = record[0]
var b = record[1]
fmt.Println(a, b)
}
}
```
**讀取結果**

### 讀寫權限的常數
```go=
os.O_RDONLY 唯讀
os.O_WRONLY 唯寫
os.O_RDWR 讀/寫
```
[**詳見官方文檔**](https://golang.org/pkg/os/#pkg-constants)
## 寫入 Write CSV
**Write寫入單行**
```go=
func Write() {
file, err := os.OpenFile(FilePath, os.O_WRONLY, 0777)
if err != nil {
log.Fatalln("找不到CSV檔案路徑:", FilePath, err)
}
w := csv.NewWriter(file)
x := []string{"999"}
w.Write(x)
w.Flush() // 把在buffer緩存中的所有資料輸出
}
```
**WriteAll寫入多行**
```go=
w := csv.NewWriter(file)
x := [][]string{{"999", "1"}, {"998", "997"}}
w.WriteAll(x)
w.Flush() // 把在buffer緩存中的所有資料輸出
```
### 寫入的坑
若開啟一個空白檔案寫入,不會有任何問題。
但若開啟已經有資料的CSV,再寫入的話會發生炸裂
**已有的原始資料**

如果寫入以下一行資料
```go=
w := csv.NewWriter(file)
x := []string{"999"}
w.Write(x)
w.Flush() // 把在buffer緩存中的所有資料輸出
```
咦~~怎麼跟我預想的結果不太一樣?!
**炸裂過後**

怎麼多了一堆莫名其妙的空格?
用EXCEL開,會看不清發生了什麼事情,
但以記事本開啟的話:
**資料從原本的狀態**

**變成這樣**

也就是說,我輸入的單行的資料是`'999'\n'`,把原始資料`1,2,3,4'\n'`給蓋過去
**將最前面四個字元覆蓋掉了**,就變成`999'\n'3,4'\n' ...`
所以用Excel打開才會被解析成上方那樣的炸裂圖。
## 附加 Append CSV
打開檔案的時候以 `O_APPEND` 模式開啟,
就能不影響舊資料,將欲寫入的資料Append在最後了。
```go
file, err := os.OpenFile(FilePath, os.O_APPEND, 0777)
```
## 其他操作方法
取代?
```go=
r, err := file.Seek(-int64(len(points)), 1)
file.Truncate(0)
```