三十二、深入Python中的文件操作
@Author: Runsen
任何語言都離不開對文件的操作,那麼Python語言是如何來操作和管理文件的。
編碼方式
編碼方式的歷史大致為ASCII
->gb2312
->unicode
->utf-8
,期間具體詳細資訊可以百度
來個編碼解碼的小例子先,記住中文可以進行GBK
和utf-8
編碼,在GBk
一個中文字元對應兩個位元組,在utf-8
一個中文字元對應三個位元組,中文不能進行ASCII
編碼。
>>> '劉潤森'.encode('GBK')
b'\xc1\xf5\xc8\xf3\xc9\xad'
>>> '劉潤森'.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
>>> 'Runsen'.encode('ascii')
b'Runsen'
>>> "劉潤森".encode('utf-8')
b'\xe5\x88\x98\xe6\xb6\xa6\xe6\xa3\xae'
>>> '劉潤森'.encode('GBK').decode('GBK')
'劉潤森'
>>> '劉潤森'.encode('GBK').decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc1 in position 0: invalid start byte
如果編碼解碼格式不一致可能會出現亂碼,encode表示編碼,decode表示解碼。
文件操作的API
下面是Python文件操作的具體的API。
方法 | 含義 |
---|---|
open | 打開 |
read | 讀取 |
write | 寫入 |
close | 關閉 |
readline | 單行讀取 |
readlines | 多行讀取 |
seek | 文件指針操作 |
tell | 讀取當前指針位置 |
打開文件
Python的open()
函數打開一個文件時,有若干個參數可用。然而,最常用的參數只有前兩個。
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
注意,第一個是強制性的,其餘的是可選的。如果不添加mode參數,文件將在Python中以只讀模式打開。
encoding:可以不寫。不寫參數,默認的編碼本是作業系統默認的編碼本。windows默認gbk,linux默認utf-8,mac默認utf-8。
f=open('test.txt',encoding='utf-8') #打開文件
data=f.read() #讀取文件
print(data)
f.close() #關閉文件
mode
mode | 含義 |
---|---|
r | 文本模式,讀取 |
rb | 二進位模式,讀取 |
w | 文本模式,寫入 |
wb | 二進位模式,寫入 |
a | 文本模式,追加 |
ab | 二進位模式,追加 |
+ | 可讀可寫 |
讀取文件
程式碼中用到的文件文件操作的1.txt 文件內容如下:
關注《Python之王》公眾號
作者:Runsen
readline(),使用該方法時,需要指定打開文件的模式為r或者r+;
readlines(),讀取全部行.返回一個列表,列表中的每個元素是原文件的每一行。如果文件很大,占記憶體,容易崩盤。
# 打開文件進行讀取
f = open("1.txt","r",encoding='utf-8')
# 根據大小讀取文件內容
print('輸出來自 read() 方法\n',f.read(2048))
# 關閉文件
f.close()
# 打開文件進行讀寫
f = open("1.txt","r+",encoding='utf-8')
# 讀取第2個字和第2行行的文件內容
print('輸出來自 readline() 方法\n',f.readline(2))
print('輸出來自 readlines() 方法\n',f.readlines(2))
# 關閉文件
f.close()
# 打開文件進行讀取和附加
f = open("1.txt","r",encoding='utf-8')
# 打開文件進行讀取和附加
print('輸出來自 readlines() 方法\n',f.readlines())
# 關閉文件
f.close()
# 輸出如下
輸出來自 read() 方法
關注《Python之王》公眾號
作者:Runsen
輸出來自 readline() 方法
關注
輸出來自 readlines() 方法
['《Python之王》公眾號\n']
輸出來自 readlines() 方法
['關注《Python之王》公眾號\n', '作者:Runsen']
寫入文件
下面只介紹清除寫 w
和追加寫 a
案例:將關注《Python之王》公眾號
寫入 test.txt 文件中
# mode=w 沒有文件就創建,有就清除內容,小心使用
with open('test.txt', 'w', encoding='utf-8') as fb:
fb.write('關注《Python之王》公眾號\n')
下面再將作者:Runsen
寫入test.txt 文件中
with open('test.txt', 'w', encoding='utf-8') as fb:
fb.write('作者:Runsen\n')
運行後會發現之前寫的關注《Python之王》公眾號
內容修改為作者:Runsen
,因為 w模式會清除原文件內容,所以小心使用。只要使用了w,就要一次性寫完。
追加寫 a
案例:將作者:Runsen
追加到 test.txt 文件中
# mode=a 追加到文件的最後
with open('test.txt', 'a', encoding='utf-8') as fb:
fb.write('關注《Python之王》公眾號\n')
with open('test.txt', 'a'encoding='utf-8') as fb:
fb.write('作者:Runsen\n')
指針操作
事物或資源都是以文件的形式存在,比如消息、共享記憶體、連接等,句柄可以理解為指向這些文件的指針。
句柄(handle)是一個來自編譯原理的術語,指的是一個句子中最先被規約的部分,所以帶有一個「句」字。
句柄的作用就是定位,兩個APi還是tell和seek。
tell返迴文件對象在文件中的當前位置,seek將文件對象移動到指定的位置,傳入的參數是offset ,表示移動的偏移量。
下面通過示例對上述函數作進一步了解,如下所示:
with open('test.txt', 'rb+') as f:
f.write(b'Runsen')
# 文件對象位置
print(f.tell())
# 移動到文件的第四個位元組
f.seek(3)
# 讀取一個位元組,文件對象向後移動一位
print(f.read(1))
print(f.tell())
# whence 為可選參數,值為 0 表示從文件開頭起算(默認值)、值為 1 表示使用當前文件位置、值為 2 表示使用文件末尾作為參考點
# 移動到倒數第二個位元組
f.seek(-2, 2)
print(f.tell())
print(f.read(1))
#輸出如下
6
b's'
4
50
b'\r'
上下文管理
我們會進行這樣的操作:打開文件,讀寫,關閉文件。程式設計師經常會忘記關閉文件。上下文管理器可以在不需要文件的時候,自動關閉文件,使用with open即可。
# with context manager
with open("new.txt", "w") as f:
print(f.closed)
f.write("Hello World!")
print(f.closed)
#輸出如下
False
True
如何批量讀取多個文件
下面,批量讀取某文件夾下的txt文件
file_list = ['1.txt', '2.txt', '3.txt','4.txt']
for path in file_list:
with open(path, encoding='utf-8') as f:
for line in f:
print(line)
下面將批量讀取文件夾下的txt文件的內容,合併內容到一個新文件5.txt中,具體實現的程式碼如下。
import os
#獲取目標文件夾的路徑
filedir = os.getcwd()+'\\'+'\\txt'
#獲取當前文件夾中的文件名稱列表
filenames = []
for i in os.listdir(filedir):
if i.split(".")[-1] == 'txt':
filenames.append(i)
#打開當前目錄下的5.txt文件,如果沒有則創建
f = open('5.txt','w')
#先遍歷文件名
for filename in filenames:
filepath = filedir+'\\'+filename
#遍歷單個文件,讀取行數
for line in open(filepath,encoding='utf-8'):
f.writelines(line)
f.write('\n')
#關閉文件
f.close()
其實在Window中只需要cd 至目標文件夾,即你需要將所有想要合併的txt文件添加至目標文件夾中,執行如下DOS命令 type *.txt > C:\目標路徑\合併後的文件名.txt
練習
題目:創建文件data.txt,文件共100000行,每行存放一個1~100之間的整數,題目來源:牛客
import random
f = open(『data.txt』,『w+』)
for i in range(100000):
f.write(str(random.randint(1,100)) + 『\n』)
f.seek(0)
print(f.read())
f.close()
題目:生成100個MAC地址並寫入文件中,MAC地址前6位(16進位)為01-AF-3B,題目來源:牛客
import random
import string
def create_mac():
MAC='01-AF-3B'
hex_num =string.hexdigits #0123456789abcdefABCDEF
for i in range(3):
n = random.sample(hex_num,2)
sn = '-' + ''.join(n).upper()
MAC += sn
return MAC
def main():
with open('mac.txt','w') as f:
for i in range(100):
mac = create_mac()
print(mac)
f.write(mac+'\n')
main()
本文已收錄 GitHub,傳送門~ ,裡面更有大廠面試完整考點,歡迎 Star。