檔案開啟和關閉
# 使用open 開啟檔案,返回時值是一個 File-like物件 f.open('/test/file') # 使用read讀取檔案 f.read( ) # 使用close關閉檔案 f.close( )
讀寫檔案
1. 檔案的操作(f.read/f.write)和檔案開啟方式(f.open)強相關
2. 字元意義:
-
'r' open for reading (default)
-
'w' open for writing, truncating the file first
-
'x' create a new file and open it for writing
-
'a' open for writing, appending to the end of the file if it exists
-
'b' binary mode
-
't' text mode (default)
-
'+' open a disk file for updating (reading and writing)
-
'U' universal newline mode (deprecated)
'r' open for reading (default)
f=open('/test/passwd',mode='r') # mode=r:可讀 f.read() # mode=r:不可寫 f.write('test write') #io.UnsupportedOperation: not writable # mode=r: 檔案不存在丟擲FileNotFoundError f=open('/test/not_exist.txt',mode='r') #FileNotFoundError: [Errno 2] No such file or directory: '/test/not_exist.txt'
'w' open for writing, truncating the file first
# 只要以mode=w方式開啟檔案,就會清空原檔案! f=open('/test/passwd',mode='w') #[root@centos1 test]# test -s /test/passwd ;echo $? #1 # mode=w 不可讀f.read() #io.UnsupportedOperation: not readable # mode=w 可寫( 覆蓋 > 寫 ) f.write('test write\n') #[root@centos1 test]# cat /test/passwd #test write # mode=w 開啟一個不存在的檔案,會建立該檔案 f=open('/test/not_exist.txt',mode='w') #[root@centos1 test]# ls /test/ |grep not_exist.txt #not_exist.txt
'x' create a new file and open it for writing
# 不能以mode=x開啟一個已存在的檔案
f=open('/test/passwd',mode='x') #FileExistsError: [Errno 17] File exists: '/test/passwd' # mode=x 總是建立新檔案 f=open('/test/not_exist.txt',mode='x') # mode=x 可寫 f.write('test write') #[root@centos1 test]# cat not_exist.txt #test write # mode=x 不可讀 f.read() #io.UnsupportedOperation: not readable
'a' open for writing, appending to the end of the file if it exists
f=open('/test/passwd',mode='a') # mode=a 不可讀
f.read() #io.UnsupportedOperation: not readable # mode=a 可寫,且是以追加到文件末尾(>>)的方式,而不是(>) f.write("zhuijia write") #[root@centos1 test]# cat passwd #test write #zhuijia write # mode=a 不存在的檔案就新建 f=open('/test/not_exist.txt',mode='a') f.write('abc') #[root@centos1 test]# cat not_exist.txt #abc
't' text mode (default) 按字元操作
'b' binary mode 按位元組操作
# mode=rt,以str方式讀取 f=open('/test/passwd',mode='rt') print(f.read()) #test content print(type(f.read())) #<class 'str'> # mode=rb,以bytes方式讀取 f=open('/test/passwd',mode='rb') print(f.read()) #b'test content\n' print(type(f.read())) #<class 'bytes'>
# mode=wt,以字元方式寫入 f=open('/test/passwd',mode='wt') print(f.write('測試')) #2 ——>輸出的是字元個數 #[root@centos1 test]# cat passwd #測試 # mode=wb,必須以bytes方式寫入 f=open('/test/passwd',mode='wb') print(f.write('測試')) #TypeError: a bytes-like object is required, not 'str' print(f.write('測試'.encode())) #6 ——>按位元組寫入是12個位元組
'+' open a disk file for updating (reading and writing)
當mode包含+時, 會增加額外的讀寫操作, 也就說原來是隻讀的,會增加可寫的操作, 原來是隻寫的,會增加可讀的操作,但是+不改變其他行為
單獨的+不能工作, mode裡必須有且僅有rwxa中的一個
# 我們可以發現以上的“rwxa”四種開啟方式,讀和寫都不能同時進行 # 且“rwxa”是兩兩之間是不能同時使用的 f=open("/test/passwd",mode="rw") #ValueError: must have exactly one of create/read/write/append mode f=open("/test/passwd",mode="r+") # mode="r+" 可讀 print(f.read()) #test content # mdoe="r+" 可寫( 追加 >> ) f.write("test2") print(f.read()) #test content #test2 f=open("/test/passwd",mode="w+") # mode="w+" 可讀 print(f.read()) #test content # mode="w+" 可寫( 覆蓋 > )f.write('test2') print(f.read()) #test2
f=open("/test/passwd",mode="a+")
# mode="a+" 讀不報錯,但內容為空 print(f.read()) #' '
# mode="a+" 可寫
print(f.write('hhh')) #3
有特定需求的讀取操作
#開啟二進位制檔案 with open("/Users/michael/test.jpg",'rb') as f: print(f.read()) #指定編碼開啟檔案 with open("/Users/gbk.txt",'r',encoding='gbk') as f: print(f.read()) #含編碼不規範的檔案開啟 with open("/Users/gbk.txt",'r',encoding='gbk',errors='ignore') as f: print(f.read()) #每次最多讀取size()位元組內容(常見於大檔案讀取防止記憶體爆的情況) read(size) #按行讀取(常用於配置檔案) readlines()
基本的寫檔案操作
with open('/Users/michael/test.txt', 'w') as f: f.write('Hello, world!')
讀寫時的指標
當開啟檔案的時候, 直譯器會持有一個指標, 指向檔案的某個位置
當我們讀寫檔案的時候,總是從指標處開始向後操作,並且移動指標
f=open("/test/aa") #預設mode="rt" print(f.tell()) #0 #當mode=r時,指標指向0(檔案開始) f.read() print(f.tell()) #13 f=open("/test/aa",mode="a") print(f.tell()) #13 #當mode=a,指標指向EOF(檔案末尾)
# seek(cookie, whence=0, /) cookie:偏移量 whence:可選引數,有3個value可選 *0:從檔案開頭開始算起 *1:從當前位置開始算起 *2:從檔案末尾算起
StringIO和BytesIO
#StringIO和BytesIO是在記憶體中操作str和bytes的方法,使得和讀寫檔案具有一致的介面 #StringIO寫 from io import StringIO f=StringIO() f.write('hello') f.write(',') f.write('world') print(f.getvalue()) # hello,world #StringIO讀 f=StringIO("hello\nhi\nworld") while True: s=f.readline() if s=='': break print(s.strip()) # hello # hi # world #BytesIO寫 from io import BytesIO f=BytesIO() f.write('xx'.encode('utf-8')) print(f.getvalue()) # b'\xe.\xb8\x89\xe.\xb8\x83' ##BytesIO讀 import codecs f=BytesIO('xx'.encode('utf-8')) print(f.read()) # b'\xe.\xb8\x89\xe.\xb8\x83'
上下文管理
File-like物件
序列化和反序列化