檔案與檔案系統

2020-08-08 21:59:58
  1. 檔案與檔案系統
    open(file, mode=‘r’, buffering=None, encoding=None, errors=None, newline=None, closefd=True) Open file and return a stream. Raise OSError upon failure.
    file: 必需,檔案路徑(相對或者絕對路徑)。
    mode: 可選,檔案開啓模式
    buffering: 設定緩衝
    encoding: 一般使用utf8
    errors: 報錯級別
    newline: 區分換行符
    常見的mode如下表所示:
    在这里插入图片描述
    【例】開啓一個檔案,並返迴檔案物件,如果該檔案無法被開啓,會拋出OSError。
f = open('將進酒.txt')
print(f)
# <_io.TextIOWrapper name='將進酒.txt' mode='r' encoding='cp936'>

for each in f:
    print(each)

# 君不見,黃河之水天上來,奔流到海不復回。
# 君不見,高堂明鏡悲白髮,朝如青絲暮成雪。
# 人生得意须盡歡,莫使金樽空對月。
# 天生我材必有用,千金散盡還復來。
# 烹羊宰牛且爲樂,會須一飲三百杯。
# 岑夫子 伕子,丹丘生,將進酒,杯莫停。
# 與君歌一曲,請君爲我傾耳聽。
# 鐘鼓饌玉不足貴,但願長醉不復醒。
# 古來聖賢皆寂寞,惟有飲者留其名。
# 陳王昔時宴平樂,鬥酒十千恣歡謔。
# 主人何爲言少錢,徑须沽取對君酌。
# 五花馬,千金裘,呼兒將出換美酒,與爾同銷萬古愁。

檔案物件方法
fileObject.close() 用於關閉一個已開啓的檔案。關閉後的檔案不能再進行讀寫操作, 否則會觸發ValueError錯誤。

```python在這裏插入程式碼片
f = open(「將進酒.txt」)
print(‘FileName:’, f.name) # FileName: 將進酒.txt
f.close()

fileObject.read([size]) 用於從檔案讀取指定的字元數,如果未給定或爲負則讀取所有。

```python
f = open('將進酒.txt', 'r')
line = f.read(20)
print("讀取的字串: %s" % line)
# 讀取的字串: 君不見,黃河之水天上來,奔流到海不復回。

f.close()

fileObject.readline()讀取整行,包括 「\n」 字元。

f = open('將進酒.txt', 'r')
line = f.readline()
print("讀取的字串: %s" % line)
# 讀取的字串: 君不見,黃河之水天上來,奔流到海不復回。
f.close()

fileObject.readline()讀取整行,包括 「\n」 字元。

f = open('將進酒.txt', 'r')
line = f.readline()
print("讀取的字串: %s" % line)
# 讀取的字串: 君不見,黃河之水天上來,奔流到海不復回。
f.close()

fileObject.readlines()用於讀取所有行(直到結束符 EOF)並返回列表,該列表可以由 Python 的 for… in … 結構進行處理。
【例】

f = open('將進酒.txt', 'r')
lines = f.readlines()
print(lines)

for each in lines:
    each.strip()
    print(each)

# 君不見,黃河之水天上來,奔流到海不復回。
# 君不見,高堂明鏡悲白髮,朝如青絲暮成雪。
# 人生得意须盡歡,莫使金樽空對月。
# 天生我材必有用,千金散盡還復來。
# 烹羊宰牛且爲樂,會須一飲三百杯。
# 岑夫子 伕子,丹丘生,將進酒,杯莫停。
# 與君歌一曲,請君爲我傾耳聽。
# 鐘鼓饌玉不足貴,但願長醉不復醒。
# 古來聖賢皆寂寞,惟有飲者留其名。
# 陳王昔時宴平樂,鬥酒十千恣歡謔。
# 主人何爲言少錢,徑须沽取對君酌。
# 五花馬,千金裘,呼兒將出換美酒,與爾同銷萬古愁。

f.close()

fileObject.tell()返迴檔案的當前位置,即檔案指針當前位置。

f = open('將進酒.txt', 'r')
line = f.readline()
print(line)
# 君不見,黃河之水天上來,奔流到海不復回。
pos = f.tell()
print(pos)  # 42
f.close()

fileObject.seek(offset[, whence])用於移動檔案讀取指針到指定位置。
offset:開始的偏移量,也就是代表需要移動偏移的位元組數,如果是負數表示從倒數第幾位開始。
whence:可選,預設值爲 0。給 offset 定義一個參數,表示要從哪個位置開始偏移;0 代表從檔案開頭開始算起,1 代表從當前位置開始算起,2 代表從檔案末尾算起。

f = open('將進酒.txt', 'r')
line = f.readline()
print(line)
# 君不見,黃河之水天上來,奔流到海不復回。
line = f.readline()
print(line)
# 君不見,高堂明鏡悲白髮,朝如青絲暮成雪。
f.seek(0, 0)
line = f.readline()
print(line)
# 君不見,黃河之水天上來,奔流到海不復回。
f.close()

簡潔的 with 語句
一些物件定義了標準的清理行爲,無論系統是否成功的使用了它,一旦不需要它了,那麼這個標準的清理行爲就會執行。

關鍵詞 with 語句就可以保證諸如檔案之類的物件在使用完之後一定會正確的執行它的清理方法。

try:
    f = open('myfile.txt', 'w')
    for line in f:
        print(line)
except OSError as error:
    print('出錯啦!%s' % str(error))
finally:
    f.close()

# 出錯啦!not readable

這段程式碼執行完畢後,就算在處理過程中出問題了,檔案 f 總是會關閉

try:
    with open('myfile.txt', 'w') as f:
        for line in f:
            print(line)
except OSError as error:
    print('出錯啦!%s' % str(error))

# 出錯啦!not readable    
  1. OS 模組中關於檔案/目錄常用的函數
    我們所知道常用的操作系統就有:Windows,Mac OS,Linu,Unix等,這些操作系統底層對於檔案系統的存取工作原理是不一樣的,因此你可能就要針對不同的系統來考慮使用哪些檔案系統模組……,這樣的做法是非常不友好且麻煩的,因爲這樣就意味着當你的程式執行環境一改變,你就要相應的去修改大量的程式碼來應對。

有了OS(Operation System)模組,我們不需要關心什麼操作系統下使用什麼模組,OS模組會幫你選擇正確的模組並呼叫。

os.getcwd()用於返回當前工作目錄。
os.chdir(path)用於改變當前工作目錄到指定的路徑。

import os

path = 'C:\\'
print("當前工作目錄 : %s" % os.getcwd())
# 當前工作目錄 : C:\Users\Administrator\PycharmProjects\untitled1
os.chdir(path)
print("目錄修改成功 : %s" % os.getcwd())
# 目錄修改成功 : C:\

listdir (path=’.’)返回path指定的資料夾包含的檔案或資料夾的名字的列表。

import os

dirs = os.listdir()
for item in dirs:
    print(item)

os.mkdir(path)建立單層目錄,如果該目錄已存在拋出異常。

import os

if os.path.isdir(r'.\b') is False:
    os.mkdir(r'.\B')
    os.mkdir(r'.\B\A')

os.mkdir(r'.\C\A') # FileNotFoundError

os.makedirs(path)用於遞回建立多層目錄,如果該目錄已存在拋出異常。

import os
os.makedirs(r'.\E\A')

os.remove(path)用於刪除指定路徑的檔案。如果指定的路徑是一個目錄,將拋出 OSError。
【例】首先建立.\E\A\text.txt檔案,然後進行刪除。

import os

print("目錄爲: %s" % os.listdir(r'.\E\A'))
os.remove(r'.\E\A\test.txt')
print("目錄爲: %s" % os.listdir(r'.\E\A'))

os.rmdir(path)用於刪除單層目錄。僅當這資料夾是空的纔可以, 否則, 拋出 OSError。
【例】首先建立.\E\A目錄,然後進行刪除。

import os

print("目錄爲: %s" % os.listdir(r'.\E'))
os.rmdir(r'.\E\A')
print("目錄爲: %s" % os.listdir(r'.\E'))

os.removedirs(path)遞回刪除目錄,從子目錄到父目錄逐層嘗試刪除,遇到目錄非空則拋出異常。
【例】首先建立.\E\A目錄,然後進行刪除。

import os

print("目錄爲: %s" % os.listdir(os.getcwd()))
os.removedirs(r'.\E\A')  # 先刪除A 然後刪除E
print("目錄爲: %s" % os.listdir(os.getcwd()))

os.rename(src, dst)方法用於命名檔案或目錄,從 src 到 dst,如果 dst 是一個存在的目錄, 將拋出 OSError。
【例】把test.txt檔案重新命名爲test2.txt。

import os

print("目錄爲: %s" % os.listdir(os.getcwd()))
os.rename("test.txt", "test2.txt")
print("重新命名成功。")
print("目錄爲: %s" % os.listdir(os.getcwd()))

os.system(command)執行系統的shell命令(將字串轉化成命令)
【例】先自行建立一個a.py的檔案,然後由shell命令開啓。

import os

path = os.getcwd() + '\\a.py'
a = os.system(r'python %s' % path)

os.system('calc')  # 開啓計算器

os.curdir指代當前目錄(.)
os.pardir指代上一級目錄(…)
os.sep輸出操作系統特定的路徑分隔符(win下爲\,Linux下爲/)
os.linesep當前平臺使用的行終止符(win下爲\r\n,Linux下爲\n)
os.name指代當前使用的操作系統(包括:‘mac’,‘nt’)

import os

print(os.curdir)  # .
print(os.pardir)  # ..
print(os.sep)  # \
print(os.linesep)
print(os.name)  # nt

os.path.basename(path)去掉目錄路徑,單獨返迴檔名
os.path.dirname(path)去掉檔名,單獨返回目錄路徑
os.path.join(path1[, path2[, …]])將 path1,path2 各部分組合成一個路徑名
os.path.split(path)分割檔名與路徑,返回(f_path,f_name)元組。如果完全使用目錄,它會將最後一個目錄作爲檔名分離,且不會判斷檔案或者目錄是否存在。
os.path.splitext(path)分離檔名與擴充套件名,返回(f_path,f_name)元組。

import os

# 返迴檔名
print(os.path.basename(r'C:\test\lsgo.txt'))  # lsgo.txt
# 返回目錄路徑
print(os.path.dirname(r'C:\test\lsgo.txt'))  # C:\test
# 將目錄和檔名合成一個路徑
print(os.path.join('C:\\', 'test', 'lsgo.txt'))  # C:\test\lsgo.txt
# 分割檔名與路徑
print(os.path.split(r'C:\test\lsgo.txt'))  # ('C:\\test', 'lsgo.txt')
# 分離檔名與擴充套件名
print(os.path.splitext(r'C:\test\lsgo.txt'))  # ('C:\\test\\lsgo', '.txt')

os.path.getsize(file)返回指定檔案大小,單位是位元組。
os.path.getatime(file)返回指定檔案最近的存取時間
os.path.getctime(file)返回指定檔案的建立時間
os.path.getmtime(file)返回指定檔案的最新的修改時間
浮點型秒數,可用time模組的gmtime()或localtime()函數換算

import os
import time

file = r'.\lsgo.txt'
print(os.path.getsize(file))  # 30
print(os.path.getatime(file))  # 1565593737.347196
print(os.path.getctime(file))  # 1565593737.347196
print(os.path.getmtime(file))  # 1565593797.9298275
print(time.gmtime(os.path.getctime(file)))
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=12, tm_hour=7, tm_min=8, tm_sec=57, tm_wday=0, tm_yday=224, tm_isdst=0)
print(time.localtime(os.path.getctime(file)))
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=12, tm_hour=15, tm_min=8, tm_sec=57, tm_wday=0, tm_yday=224, tm_isdst=0)

os.path.exists(path)判斷指定路徑(目錄或檔案)是否存在
os.path.isabs(path)判斷指定路徑是否爲絕對路徑
os.path.isdir(path)判斷指定路徑是否存在且是一個目錄
os.path.isfile(path)判斷指定路徑是否存在且是一個檔案
os.path.islink(path)判斷指定路徑是否存在且是一個符號鏈接
os.path.ismount(path)判斷指定路徑是否存在且是一個懸掛點
os.path.samefile(path1,path2)判斷path1和path2兩個路徑是否指向同一個檔案

import os

print(os.path.ismount('D:\\'))  # True
print(os.path.ismount('D:\\Test'))  # False
  1. 序列化與反序列化
    Python 的 pickle 模組實現了基本的數據序列和反序列化。

通過 pickle 模組的序列化操作我們能夠將程式中執行的物件資訊儲存到檔案中去,永久儲存。
通過 pickle 模組的反序列化操作,我們能夠從檔案中建立上一次程式儲存的物件。
pickle模組中最常用的函數爲:

pickle.dump(obj, file, [,protocol]) 將obj物件序列化存入已經開啓的file中。

obj:想要序列化的obj物件。
file:檔名稱。
protocol:序列化使用的協定。如果該項省略,則預設爲0。如果爲負值或HIGHEST_PROTOCOL,則使用最高的協定版本。
pickle.load(file) 將file中的物件序列化讀出。

file:檔名稱。

import pickle

dataList = [[1, 1, 'yes'],
            [1, 1, 'yes'],
            [1, 0, 'no'],
            [0, 1, 'no'],
            [0, 1, 'no']]
dataDic = {0: [1, 2, 3, 4],
           1: ('a', 'b'),
           2: {'c': 'yes', 'd': 'no'}}

# 使用dump()將數據序列化到檔案中
fw = open(r'.\dataFile.pkl', 'wb')

# Pickle the list using the highest protocol available.
pickle.dump(dataList, fw, -1)

# Pickle dictionary using protocol 0.
pickle.dump(dataDic, fw)
fw.close()

# 使用load()將數據從檔案中序列化讀出
fr = open('dataFile.pkl', 'rb')
data1 = pickle.load(fr)
print(data1)
data2 = pickle.load(fr)
print(data2)
fr.close()

# [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
# {0: [1, 2, 3, 4], 1: ('a', 'b'), 2: {'c': 'yes', 'd': 'no'}}