您好,登錄后才能下訂單哦!
本文實例講述了Python常見讀寫文件操作。分享給大家供大家參考,具體如下:
讀寫文件
讀寫文件是最常見的IO操作,python內置了讀寫文件的函數,用法和c是兼容的.
讀寫文件前,我們必須了解一下,在磁盤上讀寫文件的功能都是由操作系統提供的,現代操作系統不允許普通的程序直接操作磁盤,所以讀寫文件就是請求操作系統打開一個文件對象(文件描述),然后,通過操作系統提供的接口從這個文件對象中讀取數據(讀文件),或者把數據寫入這個文件對象(寫文件).
1、讀文件
要以讀文件的模式打開一個文件對象,使用python內置的open()函數,傳入文件名和標識符:
f = open("t1.txt","r",encoding="utf-8")
標識符'r'表示讀。
如果文件不存在,open()函數就會拋出一個IOError的錯誤,并且會給出詳細的錯誤碼和信息,告訴你文件不存在。
f = open("t122.txt","r",encoding="utf-8")
Traceback (most recent call last):
File "D:/Learn/python/day14/test.py", line 1, in <module>
f = open("t122.txt","r",encoding="utf-8")
FileNotFoundError: [Errno 2] No such file or directory: 't122.txt'
如果文件打開成功,接下來,調用read()方法可以一次性讀取文件的全部內容,python把內容讀取到內存,用一個str對象表示。
print(f.read())
輸出:
hello world!
最后一步調用close()方法關閉文件,文件使用完畢之后必須關閉,因為文件對象會占用操作系統的資源,并且操作系統同一時間能打開的文件數量也是有限制的。
f.close()
f = open(r"文件地址","讀取方式",encoding="utf-8")
"r":以只讀方式
encoding:讀取的編碼格式
f.read() :一次性讀取文件全部內容
f.close():關閉流
r"文件地址":不讓轉義字符“\”起作用
由于文件讀寫都有可能產生IOError,一旦出錯,后面的f.close()就不會調用,所以,為了保證文件不管是否執行出錯都能夠正確的關閉文件,我們可以使用try … finally來實現.
try: f = open("t1.txt", "r", encoding="utf-8") print(f.read()) finally: if f: f.close()
但是每次都這么寫實在太繁瑣,所以,引入了with語句來自動幫我們調用close()方法:
with open("t1.txt", "r", encoding="utf-8") as f: print(f.read())
這和前面的try…finally是一樣的,但是代碼更加簡潔,并且不必調用f.close()方法。
注意: 使用read()
會一次性讀取文件的全部內容,如果你的文件特別大,比如說有5G,那么你的內存就爆了,所以,為了保險起見,我們可以反復調用read(size)
方法,每次最多讀取size個字節內容,另外調用readline()
可以每次讀取一行內容,調用readlines()
一次性讀取所有的內容,并按行返回list,因此,要根據需要決定怎么調用。
如果文件很小,read()一次讀取最方便,如果不能確定文件大小,反復調用read(size)比較保險,如果是配置文件,調用readlines()最方便。
for line in f.readlines(): #把末尾的'\n'刪掉 print(line.strip())
2、二進制文件
前面講的默認都是讀取文本文件,并且是UTF-8編碼的文本文件,要讀取二進制文件,比如圖片,視頻等等,用'rb'模式打開文件即可:
f = open("tigle.jpg", "rb") print(f.read()) b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進制表示的字節
3、字符編碼
要讀取非UTF-8編碼的文本文件,需要給open()函數傳入encoding參數,例如,讀取GBK編碼的文件:
f = open('/user/demo/gbk.txt','r',encoding = 'gbk') f.read() '測試'
遇到有些編碼不規范的文件,你可能遇到UnicodeDecodeError,因為在文本文件中可能夾雜了一些非法編碼的字符,遇到這種情況,open()
函數還接收一個error參數,表示如果遇到編碼錯誤之后如何處理,最簡單的辦法就是直接忽略。
f = open('/users/demo/gbk.txt','r',encoding = 'gbk',errors = 'ignore')
4、寫文件
寫文件和讀文件都是一樣的,唯一的區別就是調用open()
函數時,傳入標識符'w'或者'wb'表示寫文件或寫二進制文件:
f = open("/users/demo/test.txt",'w') f.write('hello, world!') f.close()
你可以反復調用write()
來寫入文件,但是務必要調用f.close()
來關閉文件.
當我們寫入文件時,操作系統往往不會立刻把數據寫入磁盤,而是放到內存緩存起來,空閑的時候再慢慢寫入,只有調用close()
方法時,操作系統才保證把沒有寫入的數據全部寫入磁盤,忘記調用close()的后果是數據可能只寫了一部分到磁盤,剩余的丟失了,所以,還是使用with語句來的保險:
with open('/users/demo/test.txt', 'w') as f: f.write('hello, world')
要寫入特定編碼的文本文件,請給open()函數傳入encoding參數,將字符串自動轉成指定編碼。
以'w'模式寫入文件時,如果文件已經存在,直接覆蓋(相當于刪掉后新寫入一個文件),如果我們希望追加到文件的末尾怎么辦?可以傳入'a'以追加模式寫入。
with open('/users/demo/test.txt', 'a') as f: f.write('hello, world')
5、StringIO
很多時候,數據讀寫不一定是文件,也可以在內存讀寫.
stirngIO顧名思義就是在內存中讀寫str。
要把str寫入StringIO,我們需要先創建一個StringIO,然后,像文件一樣寫入即可:
from io import StringIO f = StringIO() f.write("hello") f.write(" ") f.write('world') #獲取寫入后的str print(f.getvalue())
輸出:
hello world
要讀取StringIO,可以用一個str初始化StringIO,然后,像讀文件一樣讀取:
from io import StringIO f = StringIO("Hello\nHi\nGoodBye!") while True: s = f.readline() if s == '': break # 去掉換行符 print(s.strip())
輸出:
Hello
Hi
GoodBye!
6、BytesIO
StringIO操作的只能是str,如果要操作二進制數據,就需要使用BytesIO。
BytesIO實現了在內存中讀寫bytes,我們創建一個BytesIO,然后寫入一些bytes:
from io import BytesIO f = BytesIO() f.write("中文".encode('utf-8')) print(f.getvalue())
輸出:
b'\xe4\xb8\xad\xe6\x96\x87'
注意:寫入的不是str,而是經過UTF-8編碼的bytes。
和StringIO類似,可以用一個bytes初始化BytesIO,然后,像讀文件一樣讀取:
from io import BytesIO f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87') d = f.read() print(d) print(d.decode())
輸出:
b'\xe4\xb8\xad\xe6\x96\x87'
中文
StringIO和BytesIO是在內存中操作str和bytes的方法,使得讀寫文件具有一致的接口.
7、序列化
在程序運行的過程中,所有的變量都是在內存中,比如定義一個dict
dict1 = {name:"lili",age:18}
在這里我把name進行修改,改成”leilei“,但是一旦程序結束,變量所占用的內存就會被操作系統全部回收,如果沒有把修改的name存到磁盤上,下次name初始化的時候又是”lili“
在這里我們把變量從內存中變成可存儲或者傳輸的過程稱之為序列化,在python中叫picking,序列化之后,我們就可以把序列化后的內容寫入磁盤,或是通過網絡傳輸到別的機器上。反之,把變量內容從序列化的對象重新讀取到內存里稱之為反序列化,即unpicking。
python提供了pickle模塊來實現序列化。
import pickle d = dict({"name":"lili","age":18}) #pickle.dumps()方法把任意對象序列化成一個bytes,然后就可以把bytes寫入文件 print(pickle.dumps(d)) #把序列化后的對象寫入文件 f = open("t1.txt",'wb') #參數一:要寫入的對象, 參數二:寫入文件的對象 pickle.dump(d,f) f.close() #從文件中讀取序列化后的對象 f2 = open("t1.txt","rb") #pickle.load()反序列化對象 d = pickle.load(f2) f2.close() print(d) print(type(d))
輸出:
{'name': 'lili', 'age': 18}
<class 'dict'>
注意:pickle只能用于python,并且不同版本的python彼此都不兼容,因此,只能用pickle保存一些不重要的數據,這樣即使不能成功的反序列化也沒什么關系。
8、Json
如果我們需要在不同的編程語言之間傳遞對象,那么我們必須把對象序列化成標準化格式,比如xml,但是更好的方法是json,因為json表現出來就是一個字符串,可以被所有的語言讀取,也方便存儲到磁盤或者網絡傳輸,json不僅是標準模式,并且速度也比xml更快,還可以在web中讀取,非常方便。
JSON類型 | Python類型 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int或float |
true/false | True/False |
null | None |
把python的dict對象變成一個json
import json dict1 = {"name":"lili","age":18} ji = json.dumps(dict1) print(type(ji)) with open("dd.txt","w") as f: json.dump(dict1,f) with open("dd.txt","r",encoding="utf-8") as f: du = json.load(f) print(du) print(type(du))
輸出:
<class 'str'>
{'name': 'lili', 'age': 18}
<class 'dict'>
將一個class對象序列化為json
import json class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score # 將student對象轉換為dict def student2dict(std): return { 'name': std.name, 'age': std.age, 'score': std.score } s = Student('Bob', 20, 88) # 參數一:要傳入的對象 參數二:將對象轉為dict的函數 d = json.dumps(s, default=student2dict) # 將dict轉為對象 def dict2student(d): return Student(d['name'], d['age'], d['score']) jsonStr = '{"age": 20, "score": 88, "name": "Bob"}' # json反序列化為一個對象 # 參數一:json字符串,參數二:dict轉為對象的函數 print(json.loads(jsonStr, object_hook=dict2student)) # 寫入文件 with open("t1.txt","w") as f: f.write(d) #或者直接使用下面的語句 #json.dump(s,f,default=student2dict) # 讀取文件 with open("t1.txt","r",encoding="utf-8") as f: du = json.load(f,object_hook=dict2student) print(du)
輸出:
<__main__.Student object at 0x000002CA795AA0F0>
<__main__.Student object at 0x000002CA7975B0F0>
9、讀寫csv文件
①、讀csv文件
csv文件本身就是個純文本文件,這種文件格式經常用來作為不同程序之間的數據交互的格式.
演示:
需求:讀取001.scv文件
說明:可以直接打印,然后定義list
import csv def readCsv(path): #列表 infoList = [] #以只讀的形式打開文件 with open(path, 'r') as f: #讀取文件的內容 allFileInfo = csv.reader(f) #將獲取到的內容逐行追加到列表中 for row in allFileInfo: infoList.append(row) return infoList path = r"C:\Users\xlg\Desktop\001.csv" info = readCsv(path)
②、寫csv文件
演示:
需求:向002.csv文件中寫入內容
import csv #以寫的方式打開文件 def writeCsv(path,data): with open(path,'w',newline='') as f: writer = csv.writer(f) for rowData in data: print("rowData =", rowData) #按行寫入 writer.writerow(rowData) path = r"C:\Users\xlg\Desktop\002.csv" writeCsv(path,[[1,2,3],[4,5,6],[7,8,9]])
10、讀取pdf文件
pip是一個安裝和管理python包的工具
在進行代碼演示之前,首先進行安裝和pdf相關的工具
a.在cmd中輸入以下命令: pip list [作用:列出pip下安裝的所有的工具]
b.安裝pdfminer3k,繼續輸入以下命令:pip install pdfminer3k
c.代碼演示
import sys import importlib importlib.reload(sys) from pdfminer.pdfparser import PDFParser, PDFDocument from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter #解釋器 from pdfminer.converter import PDFPageAggregator #轉換器 from pdfminer.layout import LTTextBoxHorizontal, LAParams #布局 from pdfminer.pdfinterp import PDFTextExtractionNotAllowed #是否允許pdf和text轉換 def readPDF(path, toPath): #以二進制形式打開pdf文件 f = open(path, "rb") #創建一個pdf文檔分析器 parser = PDFParser(f) #創建pdf文檔 pdfFile = PDFDocument() #鏈接分析器與文檔對象 parser.set_document(pdfFile) pdfFile.set_parser(parser) #提供初始化密碼 pdfFile.initialize() #檢測文檔是否提供txt轉換 if not pdfFile.is_extractable: raise PDFTextExtractionNotAllowed else: #解析數據 #數據管理器 manager = PDFResourceManager() #創建一個PDF設備對象 laparams = LAParams() device = PDFPageAggregator(manager, laparams=laparams) #解釋器對象 interpreter = PDFPageInterpreter(manager, device) #開始循環處理,每次處理一頁 for page in pdfFile.get_pages(): interpreter.process_page(page) layout = device.get_result() for x in layout: if (isinstance(x, LTTextBoxHorizontal)): with open(toPath, "a") as f: str = x.get_text() #print(str) f.write(str+"\n") path = r"0319開始.pdf" toPath = r"n.txt" readPDF(path, toPath)
更多關于Python相關內容感興趣的讀者可查看本站專題:《Python文件與目錄操作技巧匯總》、《Python文本文件操作技巧匯總》、《Python數據結構與算法教程》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》及《Python入門與進階經典教程》
希望本文所述對大家Python程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。