---
type: slide
tags: sprout
---
# FILE I/O, pickle, json, csv
2022 資訊之芽 北區py班
yjrubixcube
---
## 甚麼是I/O
----
I: input 輸入
O: output 輸出
今天要講的是檔案的I/O
---
# 路徑path
----
如果你在學校要找班上的1號
:male-student: :欸欸1號ㄩㄇ
----
如果要找隔壁班的1號
:female-student:: (先跑去隔壁班)欸欸1號ㄩㄇ
----
如果不想跑去隔壁班
可以用廣播
但是因為有很多班所以不能直接說1號ㄩㄇ
:speaker:: x年y班的1號ㄩㄇ
----
檔案路徑也是一樣
相對路徑vs絕對路徑
----
## 相對路徑
從你現在的資料夾開始算
![](https://i.imgur.com/NZVqbQ5.png)
假設你現在在`homework`資料夾裡面
```python=
game.py
./game.py
../homework/game.py
../schoolwork/project.py
```
`.`: 從現在的資料夾開始
`..`: 從上一層資料夾開始
----
## 絕對路徑
從最上層資料夾開始
Windows
`C:/Users/user_a/Documents/hello.py`
Mac
`/Users/user_a/Documents/hello.py`
Linux
`/media/hello.py`
---
## 開檔
----
語法
`open(路徑,模式)`
```python=
f = open("./hello.txt", 'r')
```
|模式|說明|
|-|-|
|`r` |read 讀|
|`w` |write 寫,如果檔案存在會覆蓋,不存在會建立|
|`a` |append 寫在後面|
|`x` | 建立並打開一個新檔案,可寫入|
---
## 讀檔
----
### 讀一行
```python=
f = open("hello.txt", "r")
line1 = f.readline()
print(line1, end='')
line2 = f.readline()
print(line2, end='')
```
----
### 讀幾個字元
讀14個字元
```python=
f = open("hello.txt", "r")
s = f.read(14)
print(s, end='')
```
讀第一行的前14個字元,不會讀到第二行
```python=
f = open("hello.txt", "r")
s = f.readline(14)
print(s, end='')
```
----
### 讀整個檔案
`read()`不加長度
```python=
f = open("hello.txt", 'r')
s = f.read()
print(s, end='')
```
`readlines()`回傳一個list
```python=
f = open("hello.txt", 'r')
lines = f.readlines()
for line in lines:
print(line, end='')
```
---
## 寫檔
----
```python=
f = open("hello.txt", 'w') # awx
f.write("Hello, world!\nThis is a new line!!")
f.write("This is not a new line.")
```
`write`裡面放甚麼就寫什麼
不會自動幫你換行
----
`print`大法
```python=
f = open("hello.txt", 'w')
print("Hello, world!", file=f)
f.close()
```
---
## 關檔
----
```python=
f = open("hello.txt", 'w')
f.close()
```
----
為甚麼要關檔
1. 開著佔記憶體
2. 關檔之前不會真的寫入
3. 避免開超過上限個檔案
4. 會被笑
----
如果想要馬上寫怎麼辦
```python=
f = open("hello.txt", w)
f.write("Hello, world!")
f.flush()
```
---
## 黑科技
----
這兩個是一樣的
```python=
with open("hello.txt", 'r') as f:
print(f.read())
```
```python=
f = open("hello.txt", 'r')
print(f.read())
f.close()
```
----
### 好處
- 只有在`with`裡面檔案是開的
- 不需要自己寫`close`
---
## 練習時間
[8763](https://neoj.sprout.tw/problem/8763/)
---
## Pickle
![](https://i.imgur.com/MFjosxp.jpg)
----
醃黃瓜可以用來保存蔬菜
pickle可以用來存Python的物件
----
```python=
import pickle
d = {1: 'a', 2: 'b', 3: 'c'}
l = ['abc', 'def', 123]
with open("pk_test", "wb") as f:
pickle.dump(d, f)
pickle.dump(l, f)
with open("pk_test", "rb") as f:
print(pickle.load(f))
print(pickle.load(f))
```
`b`的意思是binary file
---
## json
----
JavaScript Object Notation
可讀性比較高的儲存方式
基本上就是list跟dict的組合
適合樹狀結構
----
### json :chestnut:
```json=
{
"book": [
{
"date": "1989/06/04",
"ver": 1
},
{
"date": "2000/01/01",
"ver": 2
}
]
}
```
----
### dumps 跟 loads
`dumps`: dict/list轉str
`loads`: str轉dict/list
```python=
import json
data =
{
"book": [
{
"date": "1989/06/04",
"ver": 1
},
{
"date": "2000/01/01",
"ver": 2
}
]
}
s = json.dumps(data, indent=2)
print(s)
j = json.loads(s)
print(j)
```
----
### dump跟load
`dump`: dict/list轉str然後寫入檔案
`load`: 檔案轉dict/list
```python=
import json
with open("sample.json", 'r') as f:
j = json.load(f)
j['book'][1]["ver"] = 3
with open("changed.json", 'w') as c:
json.dump(j, c)
```
----
### [JSON formatter](https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa)
----
![](https://i.imgur.com/EHS7Tag.png)
----
![](https://i.imgur.com/IEgGeMH.png)
---
## csv
----
comma separated value
顧名思義就是用逗點分隔的值
----
||math|science|
|-|-|-|
|Alice|100|99|
|Bob|87|78|
```csv=
,"math","science"
"Alice",100,99
"Bob",87,78
```
----
### 讀csv
```python=
import csv
with open("sample.csv", 'r') as f:
reader = csv.reader(f)
for i in reader:
print(i)
```
```
['name', 'math', 'science']
['Alice', '100', '99']
['Bob', '87', '78']
```
----
### 寫csv 二維陣列版
```python=
import csv
data = [("Alice",100,99),
("Bob",87,78)]
field = ["name", "math", "science"]
with open("sample.csv", 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(field)
writer.writerows(data)
```
```csv=
name,math,science
Alice,100,99
Bob,87,78
```
----
### 寫csv dict版
```python=
import csv
data = [
{"name": "Alice", "math": 100, "science": 99},
{"name": "Bob", "math": 87, "science": 78}]
field = ["name", "math", "science"]
with open("sample.csv", 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=field)
writer.writeheader()
writer.writerows(data)
```
```csv=
name,math,science
Alice,100,99
Bob,87,78
```
---
## 延伸閱讀
- [google](https://google.com)
- [pickle官網](https://docs.python.org/3/library/pickle.html)
- [json官網](https://www.json.org/json-en.html)
- [2021資芽](https://hackmd.io/@robert1003/BkjOrzb9L#/)
- w3school