Python通用編程 - 第五章:文件處理

本文是Python通用編程系列教程,已所有更新完成,實現的目標是從零基礎開始到精通Python編程語言。本教程不是對Python的內容進行泛泛而談,而是精細化,深刻化的講解,共5個階段,25章內容。因此,須要有耐心的學習,才能真正有所收穫。雖不涉及任何框架的使用,可是會對操做系統和網絡通訊進行全局的講解,甚至會對一些開源模塊和服務器進行重寫。學完以後,你所收穫的不只僅是精通一門Python編程語言,並且具有快速學習其餘編程語言的能力,無障礙閱讀全部Python源碼的能力和對計算機與網絡的全面認識。對於零基礎的小白來講,是入門計算機領域並精通一門編程語言的絕佳教材。對於有必定Python基礎的童鞋,相信這套教程會讓你的水平更上一層樓。python

一 文件讀寫基本操做

1. 文件操做的工做流程

文件在咱們的計算機上隨處可見,當咱們須要永久保存數據的時候就會用到文件,文件是由計算機操做系統來提供的,那麼天然也就受操做系統的控制。以下圖所示,一套完整的計算機系統主要由三部分構成:編程

  1. 應用程序
  2. 操做系統
  3. 計算機底層硬件

WechatIMG33.jpeg
若是應用程序須要操做硬件,必須先要發指令給操做系統,經過操做系統來幫應用程序完成對機器硬件的操做。若是應用程序須要把本身產生的數據永久保存起來(應用程序產生的數據本來是在內存中),那麼就是把它寫入硬盤,這時應用程序要經過操做系統提供的接口來控制硬件,若是應用程序須要讀取文件內容,一樣是向操做系統發起請求,最後由操做系統返回文件內容,這之間的過程以下圖所示:
image.png
接下來咱們要講解的就是應用程序如何調用操做系統提供的接口來讀取和寫入文件。

2. 文件操做的基本形式

咱們事先在當前路徑下準備好一個文件a.txt,以下圖所示: 服務器

image.png
接下來咱們在 "文件處理.py" 文件內開始寫打開讀取文件的操做,在Python中必然會有一個功能或者接口來打開文件,這個接口就是open,使用參數以下圖所示:
image.png
文件讀取操做代碼示例以下:

""" open打開文件須要3個參數, 打開文件以後會有一個返回值, 讀寫操做就是對這個返回值進行操做 f = open('文件的路徑',mode='打開文件的模式',encoding='操做文件的字符編碼') """

""" open是向操做系統發請求,會佔用操做系統資源,這個資源不會自動回收 返回值就是應用程序拿到的變量,應用程序的變量Python解釋器會自動幫你回收 """
# 1 打開文件
f = open(r'a.txt',mode='r',encoding='utf-8')
""" 對於應用程序來講上面這行代碼與我寫一個"f = 1"沒有本質區別, 你不須要再執行"del f",由於解釋器會自動幫你清理這個應用程序資源, 可是,打開的文件佔用了操做系統的資源,這不會自動回收 """

# 2 讀取文件
data = f.read()
print(data)

# 3 關閉文件,清理操做系統打開文件的資源
f.close()
print(f)  # 應用程序的資源還在
# f.read() # 文件關閉不能再進行讀取
複製代碼

打開一個文件實際上是佔用了兩部分資源,分別是操做系統資源和應用程序資源,應用程序資源會自動由Python解釋器來回收,而操做系統打開文件的資源並不會當即回收,操做系統每打開一個文件其實會有一個編號,每一個編號與應用程序向操做系統發起文件操做請求的編號一一對應,這個編號稱爲文件描述符,操做系統的文件描述符編號是有限的,因此,當服務器高併發的時候,因爲打開文件個數很是多,於是還沒來得及關閉,那麼服務器就卡了,返回給用的的結果就是用戶的客戶端卡了。網絡

有的時候關閉文件的操做老是會被遺忘,咱們有一個使用 "with"來操做文件的方式,它是一個上下文的操做,會幫你自動的關閉文件,代碼示例以下:併發

# as 指的是賦值
with open('a.txt', 'r', encoding='utf-8') as f:
    data = f.read()
    print(data)
複製代碼

除此以外,「with」 能夠連續打開多個文件,代碼示例以下:框架

with open('a1.txt', 'r', encoding='utf-8') as f1, \
        open('a2.txt', 'r', encoding='utf-8') as f2:
    data1 = f1.read()
    data2 = f2.read()
複製代碼

二 默認打開文件的參數說明

1. 文件打開的字符編碼

若是不指定字符編碼,默認打開文件的字符編碼與操做系統相匹配:編程語言

  • Windows系統(中國大陸用戶):gbk
  • Liunx系統:utf-8
  • MacOS:utf-8

在不指定字符編碼的狀況下,MacOS系統示例代碼:高併發

# 文件保存的以utf-8編碼保存,與本機默認編碼一致
with open('a.txt', 'r', ) as f:
    data = f.read()
    print(data)
複製代碼

2. 文件的打開模式

文件默認的打開模式是「t」模式,指的是文本模式,這意味着在該模式下沒法打開圖片,視頻和音頻等文件,由於這些是以二進制格式存儲的,文本模式是以字符形式存儲的。學習

操做文件的模式有三種,分別是:「r」,「w」和「a」模式,「r」是隻讀,「w」是隻寫,「a」是指追加,默認操做文件大模式是「r」模式,因此默認文件的打開模式是「rt」模式,對於操做文本文件,「t」模式必須與操做文件的三種模式連用,不少時候你看到的,這個「t」常常會省略不寫,這是能夠的。編碼

三 文本模式打開文件的操做

1. 操做文件「r」模式

所有讀取使用read,代碼示例以下:

f = open('a.txt', mode='r', encoding='utf-8')  # 「r」模式下,若是文件不存在會報錯
# f.write('哈哈') #拋出異常,不能寫
print(f.readable())  # 判斷是否可讀
print('=============>1')
print(f.read())  # 所有讀取
print('=============>2')
# 讀文件會有一個光標移動,第一次讀完了,光標移至末尾,第二次讀無內容
print(f.read())
f.close()
複製代碼

一行一行讀文件內容使用readline,代碼示例以下:

f = open('a.txt', mode='r', encoding='utf-8')
# readline指的是一行一行讀文件
print(f.readline(), end='')  # 文件中有換行,print也自帶換行,指定end參數去掉默認換行
print(f.readline(), end='')
print(f.readline(), end='')
f.close()
複製代碼

所有讀取文件內容,存入列表,每行內容爲列表的一個元素使用readlines,代碼示例以下:

f = open('a.txt', mode='r', encoding='utf-8')

print(f.readlines()) 
f.close()
複製代碼

readlines能夠加數字做爲參數,可是他不是指的行數,而是字節數,因此咱們通常不用,如需逐行打印文件內容經常使用readlines與for循環連用,代碼示例以下:

# 若是文件內容比較少的時候,如下兩種方式均可以

with open('a.txt') as f:
    # 當文件很大時,f.readlines()結果是一個很大的列表在內存中,機器就卡了
    for line in f.readlines(): 
        print(line, end='')

# 推薦使用這種方式
with open('a.txt') as f:  # f是一個可迭代對象,就像老母雞會下蛋同樣 
    for line in f:  
      	# 文件內容很大時,使用這種方式每次內存中只有一行內容
        print(line, end='')
複製代碼

2. 操做文件「w」模式

注意:在「w」只寫模式下,當文件存在時,就會清空該文件,代碼示例以下:

f = open(r'a.txt', mode='w', encoding='utf-8')  # 默認是wt
f.write('第一行\n')  # 須要本身添加「\n」來換行
f.write('第二行\n')
f.close()
複製代碼

當文件不存在時,就會建立空文檔,代碼示例以下:

f = open(r'a1.txt', mode='w', encoding='utf-8')  # 默認是wt
f.write('第一行\n')
f.write('第二行\n')
f.close()
複製代碼

只寫模式經常使用的方法:

f = open(r'a1.txt', mode='w', encoding='utf-8')  # 默認是wt

f.writable()
# writelines指的是能夠放一個列表或者元組,裏面能夠有多行內容,須要本身加換行符
f.writelines(['111111\n', '222222\n', '333333\n'])
# 下面這樣代碼與上面寫的結果同樣
# f.write('aaaaaa\nbbbbbbb\ncccccc\n')
f.close()
複製代碼

3. 操做文件「a」模式

「a」模式指的是隻追加寫,當文件不存在時,建立空文件;當文件存在時,光標直接移至文件末尾,因此,咱們在記錄日誌的時候都會使用「a」模式,代碼示例以下:

f = open('access.log', mode='a', encoding='utf-8')
print(f.writable())
print(f.readable())
f.write('5555555555555\n')
f.close()
複製代碼

四 二進制模式打開文件的操做

1. 「b」模式基本介紹

「b」模式指的是文件打開的模式爲「b」模式, 它與「t」模式相似,不能單獨使用,必須以「rb」,「wb」或者「ab」模式來使用,「b」模式讀寫都是以bytes爲單位進行的,因此能夠理解爲「b」模式就是二進制模式。對於普通文原本說是以字符的形式保存的,可是對於圖片,視頻或者音頻等等這些文件則是以二進制形式保存的,因此「t」模式沒法讀取,代碼及報錯示例以下:

image.png
圖片文件並非以字符編碼保存的,而是以JPG這個格式保存成了二進制形式,與字符編碼沒有關係,因此咱們以文本模式處理文件是不可行的。應該以二進制模式打開文件,這時不須要指定字符編碼,正確的打開方式請看以下代碼示例:

# b模式下必定不能指定encoding參數
with open('01.jpg', 'rb', ) as f:
    data = f.read()
    print(data)
複製代碼

2. 操做文件的「rb」模式

須要說明的一點是,「b」模式也能夠讀取文本文件,字符的底層都是以二進制形式存儲的,只不過你在使用「t」模式讀取文本文件的時候open幫你把二進制轉成了可以看懂的文本,這是「t」模式的便利之處,可是它有侷限性,只能操做文本文件,而「b」模式具備統一性,任何文件底層存儲原理都是二進制,這也就是意味着「b」模式能夠操做任何文件,代碼示例以下:

with open('01.jpg', 'rb', ) as f1, open('a.txt', 'rb') as f2:
    img = f1.read()
    text = f2.read()
    print(text.decode('utf-8'))  # 把bytes轉化成utf-8
複製代碼

3. 操做文件的「wb」模式

「wb」模式也是操做文件「w」模式的一種,當文件存在時,就會清空該文件,當文件不存在時,就會建立空文件,代碼示例以下:

# wb模式寫入
with open('a.txt', 'wb') as f:
    msg = '你好,世界'
    f.write(msg.encode('utf-8'))  # 指定寫入文件的字符編碼

# rb模式讀取
with open('a.txt', 'rb') as f:
    data = f.read()
    print(data)
    print(type(data))
    print(data.decode('utf-8'))  # 指定讀取文件的字符編碼
複製代碼

4. 操做文件的「ab」模式

「ab」模式指的是以二進制形式追加寫,與操做文件的「a」模式同理,代碼示例以下:

with open('a.txt', 'ab') as f:
    msg = '\n世界:你也好,小鬼'
    f.write(msg.encode('utf-8'))  # 指定寫入文件的字符編碼
複製代碼

補充: 在這這裏講一個小模塊的部分用法,是sys模塊,它的使用說明請看下面代碼示例和截圖:

import sys  # 首先導入這個模塊

list_test = sys.argv  # 它的返回值是一個列表
print(list_test)
複製代碼

接下來咱們在終端環境下執行如下命令(注意參數1先後的空格):

image.png
你能夠看到在終端執行打印的結果就是一個列表,第一個值是文件路徑,第二個和第三個值分別是兩個參數。

5. 操做文件的其餘模式(瞭解)

通常來講,你遇到的操做文件的模式都是隻讀或者只寫,可是也有可讀可寫的模式,這類模式瞭解便可,說明和代碼示例以下:

# "r+t"模式,或者寫成"r+"模式,指的是可讀可寫
with open('a.txt', 'r+t', encoding='utf-8') as f:
    print(f.readable())
    print(f.writable())

# "w+r"或者"w+"模式,可讀可寫
with open('a.txt', 'w+t', encoding='utf-8') as f:
    print(f.readable())
    print(f.writable())

# "a+t"或者"a+",可讀可追加寫
with open('a.txt', 'a+t', encoding='utf-8') as f:
    print(f.readable())
    print(f.writable())

# "U"模式,通用換行符,已廢棄,無需瞭解
# with open('a.txt', 'U', encoding='utf-8') as f:
# print(f.readable())
# print(f.writable())
複製代碼

「r+」與「w+」,「a+」模式都是可讀可寫,他們的區別在於不改變自身本來操做文件的形式,即「r+」模式下,當文件不存在會保存,「w+」或者「a+」模式當文件不存在會建立新文件,當文件存在會清空文件。

五 文件內光標移動

在打開文件時會有一個光標移動,咱們使用seek這個方法,能夠實現光標的移動,代碼示例以下:

with open('a.txt', 'r') as f:
    f.seek(9)  # 這個參數指的是偏移量,以字節爲單位
    data = f.read()
    print(data)
複製代碼

注意:光標移動只能是從左往右移動,seek能夠加兩個參數,第一個參數就是上面代碼中的參數,你若是隻傳一個參數也就是指的這個參數,第二個參數默認是0,指的是光標在文件開頭位置開始移動,除了0以外,只能接收1或者2做爲參數,1表示從當前位置開始移動,2表示從文件末尾開始移動,其中1和2必須在「b」模式下進行,0能夠在「t」模式或者「b」下都能運行,可是不管哪一種模式,都是以bytes爲單位進行的,代碼示例以下:

with open('a.txt', 'rb') as f:
    f.seek(3, 0)  # 移動三個字節,也就是utf-8編碼下一個中文字符
    print(f.tell())  # 當前光標位置,以字節爲單位
    f.seek(3, 1)  # 從當前位置向右偏移3個字節而後再讀取文件內容
    # f.seek(3, 2) # 只能讀取動態數據新添加的內容
    data = f.read()
    print(data.decode('utf-8'))

with open('a.txt', 'r') as f:
    f.seek(3, 0)
    print(f.read())
複製代碼

補充: 在這裏補充一個小模塊的用法,是os模塊,它的使用說明請看下面代碼示例:

import os  # 首先導入這個模塊

os.rename('a.txt', 'b.txt')  # 修改文件名,兩個參數分別爲源文件名和目標文件名
os.remove('a1.txt')  # 刪除a1.txt文件,這個參數指的是文件路徑
複製代碼
相關文章
相關標籤/搜索