29.企業級開發進階1:檔案輸入輸出流[IO操作]

大牧莫邪發表於2017-05-26

農曆五月初一 宜宣告變數"a",提交程式碼;忌打DOTA,提交BUG 適宜方位:坐西朝東 多飲水、鮮奶,女神親近指數較高

進入正題

本節內容如下: * 什麼是IO * 檔案內容操作 * 操作文字檔案 * 操作二進位制檔案 * 記憶體IO * 初步認識io模組 * 目錄和檔案的操作 * 初步認識os模組 * 檔案的建立、重新命名、刪除 * 目錄的建立、重新命名、刪除 * 序列化操作

1. 什麼是IO

IO:Input/Output~輸入/輸出的意思 任何程式語言,核心都是對資料的處理,對資料的處理一般情況下就是指代資料的輸入和輸出 常規情況下,我們在程式執行的過程中,將資料頻繁的輸入或者輸出到計算機的記憶體中,讓程式正常的執行; 由於程式中的資料並不是能持久儲存的,所以在一些情況下,我們將資料輸入或者輸出到計算機中的檔案中來進行永久儲存; 所以各種程式語言中,都提供了豐富並且完善的輸入輸出流的API介面控制資料的輸入和輸出(讀/寫)~

執行中的程式,可以將資料臨時儲存在記憶體中【向記憶體中輸出資料】,也可以將記憶體中的資料讀取出來在程式中使用【向程式中輸入資料】 ```

num = 12 # 將一個資料12,賦值給變數num,num和物件12被輸出儲存到計算機記憶體中了
print (num) # 將記憶體中num對應的資料12讀取到程式中進行答應,num和對應的物件資料12被輸入到程式中了

```

記憶體中的資料讀取

同樣,執行中的程式,可以將資料永久儲存到檔案中【向檔案中輸出資料】,也可以從檔案中讀取資料到程式中使用【讀取檔案資料輸入到程式中】 從檔案中讀寫資料

2. python中的輸入/輸出

python中提供了標準的輸入/輸出的語法結構,在之前的章節中已經進行過介紹,我們這裡簡單回顧一下即可 標準輸入:input()函式操作用於接收使用者資料,儲存資料的過程就可以將資料寫入到記憶體中 標準輸出:print()函式用於將指定的資料輸出到控制檯進行展示 ```

msg = input("請輸入個人介紹:")
print("個人介紹:" + msg)

```

3. python中對檔案內容的操作

檔案內容也是一種資料,對資料的操作一般情況下可歸結為增刪改查四種方式 對檔案內容的操作,可以歸結為讀取、覆蓋、追加的操作。

python中對檔案內容的操作主要是通過open()函式進行處理的,open()函式的簡單語法結構如下: ```

open(file, mode="r", buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

# file:是要操作的檔案,這裡是完整的問檔案路徑+檔名稱,如:d:/test.txt

# mode:是操作預設,預設是r,表示可讀的
####  常規選項如下:
#### r     #### 表示檔案以可讀的方式開啟,開啟的檔案只能讀取檔案資料,不能修改
#### w     #### 表示檔案以可寫的方式開啟,可以操作檔案中的資料,不能做其他操作
#### x     #### 表示檔案以執行的方式開啟,主要用於進行檔案建立等操作
#### a     #### 表示檔案內容以追加的方式開啟,向檔案寫入資料不會覆蓋原來的資料
#### b     #### 表示檔案以二進位制的方式進行處理,可以操作二進位制資料
#### t     #### 表示檔案以文字的方式進行處理,也是預設的方式
#### +     #### 表示檔案以讀寫的方式進行處理,是rw結合起來的用法
#### U     #### 表示使用通用的內容換行的方式進行處理

# buffering:表示讀寫內容的緩衝區,如果設定為0表示關閉緩衝區,通常情況下我們會使用io.DEFAULT_BUFFER_SIZE這個預設值,在不同的作業系統中是4096/8192位元組的長度

# encoding:開啟檔案的編碼,這個選項只能用於操作文字檔案的情況下,這個選項的預設值跟檔案所在的作業系統有關

# errors:這個選項主要用於在encoding選項進行編碼和解碼出現錯誤時的操作,值是一個字串,python已經封裝了字串對應的處理功能;常規的選項如下:
#### strict    #### 使用嚴格模式進行處理,如果出現錯誤就丟擲ValueError異常資訊
#### ignore    #### 忽略出現的錯誤,這裡需要注意,忽略編碼錯誤會導致資料丟失的!
#### replace   #### 如果出現編碼錯誤,使用特殊符號替換錯誤的編碼,如符號?

# newline:選項用於控制mode為U時自動換行的處理,可以是如下選項中的一種
#### "None"、""、"\n"、"\r"、"\r\n"

```

3.1. 操作文字檔案
  • 讀取文字檔案中的資料,可以使用read()函式讀取所有資料或者read(size)讀取指定長度的資料或者readlines()讀取整行資料

```

# 以只讀的方式開啟系統中d:/test.txt文字檔案,讀取其中的資料
f = open("d:/test.txt", "r")

# 讀取資料到程式中
content = f.read()

# 使用讀取到的資料
print(content)

# 操作結果,記得關閉檔案哦
f.close()

# 執行結果:d:/test.txt中的資料被完整的讀取出來了
~hello python!
~輸入輸出流測試資料!

```

上述程式碼在執行時,如果操作的檔案不存在就會出現如下錯誤,請按照之前的錯誤除錯章節的內容分析一下錯誤 ```

Traceback (most recent call last):
  File "D:/resp_work/PY_WORK/備課/模組化開發/demo06/demo01檔案操作.py", line 3, in <module>
    f = open("d:/testtxt", "r")
FileNotFoundError: [Errno 2] No such file or directory: 'd:/test.txt'

```

另外,在讀取檔案資料時,一定要注意檔案的編碼格式,通常情況下都是使用當前作業系統預設的編碼,也就是在函式處理時忽略encoding選項;如同下面的情況就會出現問題:

我當前系統的預設編碼是gbk編碼,在d:盤下建立了一個test2.txt檔案,檔案編碼修改成了utf-8編碼,此時執行如下程式碼: ```

f = open("d:/test2.txt", "r")
content = f.read()
print(content)
f.close()

我們可以看到和前面的程式碼沒有任何區別,但是執行出現如下問題:

Traceback (most recent call last):
  File "D:/resp_work/PY_WORK/備課/模組化開發/demo06/demo01檔案操作.py", line 26, in <module>
    content = f.read()
UnicodeDecodeError: 'gbk' codec can't decode byte 0xaf in position 8: illegal multibyte sequence

這是一個什麼樣的問題呢:報錯提示`UnicodeDecodeError`也就是編碼錯誤,我們修改程式程式碼

f = open("d:/test2.txt", "r", encoding="utf-8")
content = f.read()
print(content)
f.close()

重新執行程式,資料正常讀取了

這是新的檔案內容

```

  • 向文字檔案中寫入資料,一般情況下,可以通過write()函式或者writelines()函式向檔案中寫入資料

```

# 以可寫的方式開啟d:/test.txt檔案
# 這裡請注意,open()函式的mode是w模式,如果目標檔案不存在就會自動建立這個檔案
f = open("d:/test.txt", "w")

# 通過write()函式向檔案中寫入資料
f.write("這是Python從程式中寫入到檔案的資料")

# 操作完成,一定記得關閉檔案哦
f.close()

```

python程式寫入檔案的資料

  • 向文字檔案中追加寫入資料,上面的程式碼執行的結果,會將檔案中原來的資料覆蓋掉

```

# 以追加內容的方式開啟檔案
f = open("d:/test.txt", "a")

# 向檔案中追加內容
f.write("這是新的內容")

# 操作完成,記得關閉檔案哦
f.close()

```

我們開啟檔案可以看到,原來的資料還在,新的資料被追加到了後面 追加寫入資料

3.2. 操作二進位制檔案
  • 以二進位制的方式開啟檔案讀取檔案中的資料【文字檔案也可以按照二進位制檔案的方式讀取】

```

# 按照二進位制的方式讀取檔案,mode可以設定為rb兩個選項配合
f = open("d:/test.txt", "rb")

# 讀取檔案資料
content = f.read()

# 使用檔案中的資料
print(content)

# 操作完畢,記得關閉檔案哦
f.close()

# 執行結果如下:
~b'\xd5\xe2\xca\xc7Python\xb3\xcc\xd0\xf2\xd0\xb4\xc8\xeb\xce\xc4\xbc\xfe\xb5\xc4\xca\xfd\xbe\xdd\xd5\xe2\xca\xc7\xd0\xc2\xb5\xc4\xc4\xda\xc8\xdd'

```

  • 以二進位制的方式,向檔案中寫入資料

```

# 定義要寫入檔案中的內容
s = "這是python按照二進位制寫入的資料"

# 按照二進位制的方式開啟檔案追加內容,mode可以設定為ab兩個選項配合
f = open("d:/test.txt", "ab")

# 向檔案中寫入資料
f.write(bytes(s, encoding="utf-8"))

# 使用檔案中的資料
print(content)

# 操作完畢,記得關閉檔案哦
f.close()

```

bytes(str, encoding="")這是一個將字串轉換成位元組陣列的函式,寫入完成後檢視檔案內容如下: 紅色部分是寫入的二進位制資料

4. python中對記憶體IO

python程式對資料的輸入輸出,不一定都是針對檔案的,也可以是針對記憶體的處理 常規情況下,python提供了StringIOBytesIO兩個內建類來進行記憶體中資料的處理 注意:需要引入python中的io模組 * StringIO:在記憶體中讀寫字串的內建類 * BytesIO:在記憶體中讀寫二進位制資料的內建類

4.1 記憶體中讀寫字串
  • 記憶體中讀寫字串 常規情況下就是建立一個StringIO物件,然後按照正常的檔案讀寫的方式進行內容的讀寫即可

```

# 引入需要的模組
from io import StringIO

# 建立StringIO物件
s = StringIO()

# 向記憶體中寫入資料
s.write("儲存在記憶體中的資料:使用者名稱")
s.write("內容預設是追加的")

# 從記憶體中讀取資料
content = s.getvalue()
print(content)

# 操作完成,適當的時刻關閉物件
s.close()

```

  • 記憶體中操作二進位制資料:和StringIO基本一致

```

# 引入需要的模組
from io import BytesIO

# 定義要寫入的資料,使用bytes()函式轉換成二進位制資料
s = "這是要寫入的資料"
sc = bytes(s, encoding="utf-8")

# 建立BytesIO物件
b = BytesIO()

# 向記憶體中寫入資料
b.write(sc)

# 從記憶體中讀取資料
content = b.getvalue()
print(content)

# 操作完成,適當的時刻關閉物件
s.close()

# 執行結果
~b'\xe8\xbf\x99\xe6\x98\xaf\xe8\xa6\x81\xe4\xbf\x9d\xe5\xad\x98\xe7\x9a\x84\xe6\x95\xb0\xe6\x8d\xae'

```

5. python中對目錄/路徑/資料夾的操作

本節內容所有的操作,其實都是和計算機互動的操作~操作計算機的記憶體、檔案等等,python程式本身是做不了這些事情的,只是python在底層進行了和作業系統互動的功能封裝,將作業系統可以執行的諸如建立檔案、檔案內容操作、記憶體操作等等封裝成了函式

簡單瞭解os模組,os模組主要是針對作業系統的API的封裝 ```

# 引入os模組
import os

# 檢視作業系統型別
# nt表示windows作業系統;posix表示Unix/Linux或者MacOS系統
os.name
~ 執行結果:nt

# 檢視作業系統中的環境變數
os.environ
~執行結果:environ({'ALLUSERSPROFILE': 'C:\\ProgramData', 'APPDATA': 'C:\\Users\\mouwe\\AppData\\Roaming',.................'CLASSPATH': 'D:\\resp_application\\Java\\jdk1.8.0_121\\lib;.;',})

```

5.1. 操作檔案目錄

```

# 檢視當前作業系統的絕對路徑
os.path.abspath(".")
~ 執行結果:D:\resp_work\PY_WORK\demo
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 建立指定單級目錄
# 語法結構:os.mkdir(path, mode=, dir_fd=None)
# 描述:mkdir()函式用於使用指定的mode選項來建立一個資料夾目錄
# 引數path:用於建立資料夾的路徑
# 引數mode:用於設定的許可權數字,預設777(所有許可權:讀寫執行[rwx])
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 在d盤中建立一個目錄,目錄名稱為test
os.mkdir("d:/test") 

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 建立指定多級目錄
# 語法結構:os.mkdirs(path, mode=, exist_ok=False)
# 描述:makedirs()函式用於使用指定的mode選項來建立一系列資料夾目錄
# 引數path:用於建立資料夾的路徑
# 引數mode:用於設定的許可權數字,預設777(所有許可權:讀寫執行[rwx])
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 在d盤中建立test資料夾,資料夾中包含test2資料夾,test2中包含test3資料夾
os.mkdirs("d:/test/test2/test3")

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 重新命名
# 語法結構:os.rename(old, new)
# 描述:rename()函式用於使用新名稱重新命名資料夾或者檔案
# 引數old:要重新命名的檔案
# 引數new:檔案的新名稱
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
os.rename("d:/test", "d:/new")

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 刪除檔案或者目錄
# 語法結構:os.rmdir(path)
# 描述:rmdir()函式用於刪除指定路徑的資料夾或者檔案
# 引數path:要刪除的資料夾或者檔案的路徑
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
os.rm("d:/test")

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 刪除多級資料夾
# 語法結構:os.removedirs(path)
# 描述:removedirs(path)
# 引數path:要刪除的多級資料夾路徑
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
os.removedirs("d:/test/test2/test3")

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 同樣在進行資料夾或者檔案刪除的時候,首先要進行資料驗證
# 也就是首先判斷是資料夾/檔案,才去執行刪除操作
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# os.path.exists(path)函式用於判斷指定的路徑是否存在,存在返回True
res = os.path.exists("d:/test")

# os.path.isdir(path)函式用於判斷指定的路徑是否資料夾,是則返回True
res = os.path.isdir("d:/test")

# os.path.isfile(path)函式用於判斷指定的路徑是否檔案,是則返回True
res = os.path.isfile("d:/test")

```

對於檔案和資料夾的初步操作,暫時先分析到這裡,再後面的章節中學習過多執行緒等操作之後再深入分析

相關文章