python3基礎:檔案操作
相對路徑和絕對路徑
相對路徑:顧名思義就是相對於當前檔案的路徑。網頁中一般表示路徑使用這個方法。
絕對路徑:絕對路徑就是主頁上的檔案或目錄在硬碟上真正的路徑。
比如 c:/apache/cgi-bin 下的,那麼 c:/apache/cgi-bin就是cgi-bin目錄的絕對路徑
檔案操作模式
檔案操作常用方法:
open()函式:
open()函式,用來開啟一個檔案,返回新開啟檔案的描述符
語法:
open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
引數說明:
file:檔名稱
mode:指定檔案的開啟方式,其中,‘rt’為預設方式(t也就是text,代表文字檔案)
encoding:編碼或者解碼方式。預設編碼方式依賴平臺,如果需要特殊
設定,可以參考codecs模組,獲取編碼列表。encoding不寫的話預設用的是GBK
newline:換行控制,引數有:None,’\n’,’\r’,’\r\n。為None的話,寫‘\r’‘\r\n’‘\n’的話全部轉換成‘\n’
程式碼示例1:換行控制
>>> with open('b.txt','w+',encoding='utf-8') as fp: ... fp.write('a\r\nb\rc\nd') ... 8 >>> with open('b.txt',encoding='utf-8') as fp: ... fp.read() ... 'a\n\nb\nc\nd'
程式碼示例2:分別以r+/w+/a+方式讀寫檔案
r+
>>> fp = open("e:\\a.txt","r+")
>>> fp.read()#檔案指標在開頭,不會清空檔案,所以能讀出內容
'a\n\nb\nc\nd'
>>> fp.tell()
10
>>> fp.write("hello")
5
>>> fp.seek(0,0)
0
>>> fp.read()
'a\n\nb\nc\ndhello'
>>> fp.close()
a+
>>> fp = open("e:\\a.txt","a+") >>> fp.read()#檔案指標在末尾,所以讀出的是空字串 '' >>> fp.tell() 15 >>> fp.seek(0,0) 0 >>> fp.read()#不會清空檔案,所以檔案指標回到開頭後能讀出內容 'a\n\nb\nc\ndhello' >>> fp.tell() 15 >>> fp.seek(0,0) 0 >>> fp.write("world!")#不管遊標在哪裡,都是在最後去寫入 6 >>> fp.seek(0,0) 0 >>> fp.read()#不管遊標在哪裡,都是在最後去寫入 'a\n\nb\nc\ndhelloworld!' >>> fp.close()
w+:w模式即使什麼都沒做都會把檔案清空,而且沒有提示
>>> fp = open("e:\\a.txt","w+")
>>> fp.tell()
0
>>> fp.read()#會把檔案清空,所以讀不出來
''
>>> fp.write("hello world!")
12
>>> fp.read()#write完成後是在檔案的最後,所以讀不出來
''
>>> fp.seek(0,0)
0
>>> fp.read()
'hello world!'
>>> fp.close()
with上下文管理的原理
實現了上下文管理,__enter__實現初始化的工作,並且返回一個值;所有程式執行完之後自動呼叫__exit__執行回收的工作
class Sample:
def __enter__(self):
print("In __enter__()")
return "Foo"
def __exit__(self,type,value,trace):
print("In __exit__()")
def get_sample():
return Sample()
with get_sample() as sample:#__enter__()返回的值賦給sample
print("sample:",sample)
執行結果:
檔案物件
底層檔案描述符是一個數字,類似於控制代碼。一個檔案被開啟後,你就會得到一個檔案描述符,然後就可以得到有關該檔案的各種資訊
屬性 描述
file.closed 返回true如果檔案已被關閉,否則返回false
file.mode 返回被開啟檔案的訪問模式
file.name 返回檔案的名稱
程式碼示例:’’‘檔案物件’’’
fp = open( "a.py",'w')
print ("檔案是否關閉:", fp.closed)
print ("檔案的訪問模式:", fp.mode)
print ("檔名稱:", fp.name)
#關閉檔案
fp.close()
read([size]):讀取檔案
size為讀取的長度,以byte為單位。如果不指定引數的話,表示一次性讀取全部的檔案內容,並以字串形式返回,並且每一行的結尾會有一個"\n"符號。
程式碼示例:
>>> fp = open('cc.txt')
>>> fp.read()
'1234b67890\n'
>>> fp.close()
>>>
>>> fp = open('cc.txt')
>>> fp.read(5)
'1234b'
>>> fp.close()
readline([size]):讀取檔案
讀取一行,如果給定了size有可能返回的只是一行的一部分,以字串的形式返
回,並且結尾會有一個換行符"\n"。讀完一行,檔案操作標記移動到下一行的
開頭。
程式碼示例:
>>> fp = open('f.txt')
>>> fp.readline(3)
'hel'
>>> fp.readline(3)
'lo '
>>> fp.readline(3)
'wor'
>>> fp.readline(3)
'ld!'
>>> fp.readline(3)#大於某行剩餘的字元時只返回剩餘的字元
'1\n'
>>> fp.readline(3)
'hel'
>>> fp.readline(3)
readlines([size]):讀取檔案
把檔案每一行作為一個list的一個成員,是一個字串,並且結尾會有一個換行符"\n",並返回這個list。這個函式的內部是通過迴圈呼叫readline()來實現的。如果指定了size引數,表示讀取檔案指定內容的長度,此時就有可能只能讀取檔案的一部分,並且結尾會有一個換行符"\n"。
readlines(hint=-1)
Read and return a list of lines from the stream. hint can be specified to control the number of lines read: no more lines will be read if the total size (in bytes/characters) of all lines so far exceeds hint.
‘test.txt’中有3行內容:
>>> fp = open('test.txt')
>>> fp.readlines()#讀取全部檔案內容並以列表返回
['python\n', 'java\n', 'c++\n']
>>> fp.seek(0,0)
0
>>> for i in range(16):
... print(fp.readlines(i))
... fp.seek(0,0)
...
['python\n', 'java\n', 'c++\n']#i=0
['python\n']#i=1
['python\n']#i=2
['python\n']#i=3
['python\n']#i=4
['python\n']#i=5
['python\n']#i=6
['python\n', 'java\n']#i=7
['python\n', 'java\n']#i=8
['python\n', 'java\n']#i=9
['python\n', 'java\n']#i=10
['python\n', 'java\n']#i=11
['python\n', 'java\n', 'c++\n']#i=12
['python\n', 'java\n', 'c++\n']#i=13
['python\n', 'java\n', 'c++\n']#i=14
['python\n', 'java\n', 'c++\n']#i=15
總結:
當指定的size等於0或者大於檔案總大小時返回的都是全部檔案內容;
當指定的size小於一行檔案的字元數時返回的時一行檔案;
同理。。。。
write(str):將字串寫入檔案中
把str寫到檔案中,預設是不加換行符的,所以如果想換行的話,得手動加入換行符’\n’
程式碼示例:’’‘將a26 b25…z1輸出到檔案中’’’
with open('aa.txt','w+',encoding='utf-8') as fp:
for i in range(26,0,-1):
fp.write(chr(ord('z')-i+1)+str(i)+'\n')
writelines(seq):將序列寫入檔案中
把seq(序列)的內容全部寫到檔案中(多行一次性寫入),也不會自動加入換行符。
注意:序列中的內容也必須是字串型別的資料,才能成功寫入檔案
>>> fp = open("e:\\a.txt",'w')
>>> fp.writelines(["1\n","2\n","3\n"])
>>> fp.close()
close():關閉檔案
重新整理緩衝區裡任何還沒寫入的資訊,並關閉該檔案,不能再進行寫入。用 close()方法關閉檔案是一個很好的習慣。如果檔案關閉後,還對檔案進行操作就會產生ValueError錯誤,但如果不及時關閉檔案,有可能產生控制代碼洩露,丟失資料。而且不關閉檔案的話佔資源,浪費控制代碼數量,控制代碼數量有限 。
程式碼示例:
>>> fp = open('test.txt')
>>> fp.close()
>>> print('檔案是否關閉:',fp.closed)
檔案是否關閉: True
flush():將緩衝區指定內容寫入硬碟
程式碼示例:
testList = ['test1\n', 'test2\n', 'test3', '檔案操作']
fp = open( "bb.txt",'w+')
print (fp.read(),end="\n")
fp.writelines(testList)
fp.flush()
fp1 = open( "bb.txt",'r')
print (fp1.read(),end="\n")
fp.close()
fp1.close()
fileno():返回長整形的檔案標籤
>>> fp = open("a.txt")
>>> fp.fileno
<built-in method fileno of _io.TextIOWrapper object at 0x0000000000387B40>
>>> fp.fileno()
3
tell():返回檔案操作標記的當前位置
以檔案的開頭為基準點
程式碼示例:
>>> fp = open('test.txt')
>>> fp.tell()
0
>>> fp.readline()
'python\n'
>>> fp.tell()
8
>>> fp.close()
seek(offset[,from]):檔案定位
作用:改變當前檔案的位置。
引數說明:
Offset:表示要移動的位元組數;
From:指定開始移動位元組的參考位置。如果from
設為0(預設值):將檔案的開頭作為移動位元組的參考位置;
設為1:則使用當前的位置作為參考位置;
設為2:那麼該檔案的末尾將作為參考位置。
注意:
如果檔案以a或a+的模式開啟,每次進行寫操作時,檔案操作標記會自動返回到檔案末尾
檔案必須是以二進位制形式開啟的才能以當前位置或末尾為參考位置進行定位。
程式碼示例:
>>> fp =open('aa.txt')
>>> fp.read()
'a26\nb25\nc24\nd23\ne22\nf21\ng20\nh19\ni18\nj17\nk16\nl15\nm14\nn13\no12\np11\
nq10\nr9\ns8\nt7\nu6\nv5\nw4\nx3\ny2\nz1\n'
>>> fp.seek(-5,2)#以文字形式開啟的檔案,以末尾為參考位置報錯
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
io.UnsupportedOperation: can't do nonzero end-relative seeks
>>>
>>> fp = open("a.txt","rb+")
>>> fp.read()
b'1234aaxxx\r\ngloryroad\r\nbxxxx\r\n'
>>> fp.tell()
29
>>> fp.seek(5,1)
34
>>> fp.seek(-5,1)
29
>>> fp.seek(-5,1)
24
>>> fp.read()
b'xxx\r\n'
>>> fp.seek(-5,1)
24
>>> fp.seek(2,1)
26
>>> fp.read()
b'x\r\n'
>>>
>>> fp =open('aa.txt','rb')
>>> fp.read()
b'a26\r\nb25\r\nc24\r\nd23\r\ne22\r\nf21\r\ng20\r\nh19\r\ni18\r\nj17\r\nk16\r\nl
15\r\nm14\r\nn13\r\no12\r\np11\r\nq10\r\nr9\r\ns8\r\nt7\r\nu6\r\nv5\r\nw4\r\nx3\
r\ny2\r\nz1\r\n'
>>> fp.seek(-5,2)
116
>>> fp.read()
b'\nz1\r\n'
>>> fp.seek(5,1)
126
>>> fp.read()
b''
>>> fp.seek(-5,1)
121
>>> fp.read()
b''
>>> fp.seek(-20,2)
101
>>> fp.read()
b'v5\r\nw4\r\nx3\r\ny2\r\nz1\r\n'
truncate([size]):裁剪檔案
把檔案裁成規定的大小,預設的是裁到當前檔案操作標記的位置。如果size比檔案的大小還要大,依據系統的不同可能是不改變檔案,也可能是用0把檔案補到相應的大小,也可能是以一些隨機的內容加上去。
程式碼示例:’’’’’’
fp = open('dd.txt','r+',encoding='utf-8')
fp.readline()
fp.truncate(20)
print(fp.tell())
print(fp.read())
fp.close()
‘’‘讀取檔案中指定的行數’’’
#方法一:
with open('dd.txt',encoding='utf-8') as fp:
print(fp.readlines()[1])
#方法二:
count=0
fp = open('dd.txt',encoding='utf-8')
for line in fp:
count+=1
if count ==2:
print(line)
fp.close()
linecache 模組
linecache 模組允許從任何檔案裡得到任何的行,並且使用快取進行優化,常見的情況是從單個檔案讀取多行。
程式碼示例:’’’’’’
import linecache
file_content= linecache.getlines('c:\\1.txt')#所有檔案內容以列表的形式快取到記憶體
print (file_content)
file_content =linecache.getlines('c:\\1.txt')[0:4]
print (file_content)
file_content =linecache.getline('c:\\1.txt',2)#讀取指定行
print (file_content)
file_content =linecache.updatecache('c:\\1.txt')
print (file_content)
#更新快取
linecache.checkcache('c:\\1.txt')
#清理快取,如果你不再需要先前從getline()中得到的行
linecache.clearcache()
1.3.pickle模組:持久化/序列化
python中的物件是不能儲存的,關閉程式後所有的變數或者物件都沒有了。持久地儲存物件(序列化)可以在一個檔案中儲存任何Python物件,之後又可以把它完整無缺地取出來。
使用場景:用檔案的方式儲存資料,或者不同系統之間交換資料時使用
import pickle as p
shoplistfile = 'e:\\shoplist.data'
#the name of the file where we will store the object
shoplist = ['apple', 'mango', 'carrot']
animallist=['hippo','rabbit']
#Write to the file
f = open(shoplistfile, 'wb')
p.dump(shoplist, f) # dump the object to a file
p.dump(animallist,f)
f.close()
del shoplist # remove the shoplist
del animallist
#Read back from the storage
f = open(shoplistfile,'rb')
storedlist = p.load(f)#先進先出
animallist= p.load(f)
print (storedlist)
print (animallist)
注意:load時必須按dump時的先後順序,沒有辦法判斷反序列化之後的型別,所以必須要指定dump時的順序,而且時先進先出
靈活使用可參考shelve模組也是 用來持久化任意的Python物件