24-python文件IO(一)

01-上章題目講解:在上一章節(jié)里

02-open方法和模式

文件操作:非常重要

馮諾依曼體系架構(gòu)


image.png

內(nèi)存:掉電易失
CPU由運(yùn)算器和控制器組成:

  • 運(yùn)算器搜吧,完成各種算數(shù)運(yùn)算蚕愤,邏輯運(yùn)算尤溜,數(shù)據(jù)傳輸?shù)葦?shù)據(jù)加工處理
  • 控制器,控制程序執(zhí)行
  • 存儲(chǔ)器浩聋,用于記憶程序和數(shù)據(jù)祟昭,例如內(nèi)存
  • 輸入設(shè)備,將數(shù)據(jù)或者程序輸入到計(jì)算機(jī)中蒂誉,例如鍵盤教藻,鼠標(biāo)
  • 輸出設(shè)備,將數(shù)據(jù)或程序的處理結(jié)果展示給用戶拗盒,例如顯示器怖竭,打印機(jī)等
    一般說(shuō)IO操作,指的是文件IO,如果指的是網(wǎng)絡(luò)IO陡蝇,都會(huì)直接說(shuō)網(wǎng)絡(luò)IO
    機(jī)械磁盤上存的都是二進(jìn)制痊臭,且存儲(chǔ)的數(shù)據(jù)未必是連續(xù)的,所以叫機(jī)械硬盤也叫隨機(jī)訪問(wèn)設(shè)備登夫。

文件IO常用操作

image.png

打開(kāi)操作

文件系統(tǒng)是靠目錄管理广匙,文件一定是放在目錄下的;windows和linux文件系統(tǒng)不一樣恼策;windows系統(tǒng)是帶邏輯驅(qū)動(dòng)器鸦致,邏輯驅(qū)動(dòng)器有自己的根潮剪,因?yàn)橛羞壿嬺?qū)動(dòng)器,所以要加盤符分唾;linux是根文件系統(tǒng)抗碰。


image.png

f = open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True,opener=None)
打開(kāi)一個(gè)文件,返回一個(gè)文件操作對(duì)象(流對(duì)象)和文件描述符绽乔。打開(kāi)文件失敗弧蝇,則返回異常。打開(kāi)后一定要關(guān)閉折砸。
基本使用:
創(chuàng)建一個(gè)文件test看疗,然后打開(kāi)它,用完關(guān)閉

image.png

其中的encoding='cp936',cp936的cp代表codepage睦授,等于gbk編碼两芳;windows默認(rèn)編碼是gbk,linux這是UTF-8;gbk編碼中文是2字節(jié)去枷;UTF-8 編碼常見(jiàn)中文是3個(gè)字節(jié)怖辆;GBK兼容GB2312編碼,但比GB2312包含了更多的漢字:中文存儲(chǔ)時(shí)沉填,第一個(gè)字節(jié)碼值在127256之間疗隶,第二個(gè)字節(jié)碼值在0256之間。
Ipython環(huán)境下運(yùn)行shell命令(前提是linux系統(tǒng)裝的有ipython翼闹,這樣在ipython環(huán)境下運(yùn)行shell命令時(shí)才可以)斑鼻,需要在命令前加 ! ,例如 !ls
文件訪問(wèn)的模式有2種:文本模式(字符訪問(wèn),與編碼有關(guān))和二進(jìn)制模式(字節(jié)流訪問(wèn)猎荠,不管編碼)坚弱。不同模式下,操作函數(shù)不盡相同关摇,表現(xiàn)的結(jié)果也不一樣荒叶。

open的參數(shù)

mode模式

image.png
r read

只讀打開(kāi)文件,如果使用write方法會(huì)拋異常输虱。
如果文件不存在些楣,拋出FileNotFoundError異常

w write

表示只寫方式打開(kāi),如果讀取則拋出異常
如果文件不存在宪睹,則直接創(chuàng)建文件
如果文件存在愁茁,則清空文件內(nèi)容
w:沒(méi)有的話創(chuàng)建,有的話直接覆蓋
f = open('test','w')
f.close
以上兩行可以創(chuàng)建一個(gè)空文件


image.png

print后 會(huì)返回寫進(jìn)去的字符數(shù)量

x create

文件不存在直接創(chuàng)建亭病,并只寫方式打開(kāi)
文件已存在鹅很,會(huì)拋FileExistsError異常

a append

文件存在,只寫打開(kāi)罪帖,追加內(nèi)容
文件不存在促煮,則創(chuàng)建后邮屁,只寫打開(kāi),追加內(nèi)容菠齿。

總結(jié)以上幾種模式

r是只讀佑吝,wxa都是只寫。
wxa都可以產(chǎn)生新的文件泞当,w不管文件存在與否迹蛤,都會(huì)生成全新內(nèi)容的文件民珍;a不管文件是否存在襟士,都能在打開(kāi)的文件尾部追加;x必須要求文件事先不存在嚷量,自己造一個(gè)新文件陋桂。

文本模式t:操作單位是字符

字符流,將文件的字節(jié)按照某種字符編碼理解蝶溶,按照字符操作嗜历。open的默認(rèn)mode是rt

二進(jìn)制模式b:

字節(jié)流,將文件按照字節(jié)理解抖所,與字符編碼無(wú)關(guān)梨州。二進(jìn)制模式操作時(shí),字節(jié)操作使用bytes類型
一個(gè)文件讀取的編碼方式要和寫入時(shí)的編碼方式一致田轧,否則讀取時(shí)會(huì)出現(xiàn)亂碼暴匠。
二進(jìn)制操作寫入中文到文件中:

f = open('test3','wb')
#f.write('啊')  #TypeError: a bytes-like object is required, not 'str' 需要像bytes一樣的東西,不要字符串
#f.write(b'啊') #bytes can only contain ASCII literal characters  只認(rèn)ASII傻粘,這樣寫不行
f.write('啊'.encode('gbk')) #encode 默認(rèn)編碼方式為 utf-8. 啊 用utf-8編碼占3個(gè)字節(jié):b'\xe5\x95\x8a'  漢字的正確編碼方式為gbk
f.close()

f = open('test3','r',encoding='gbk')
print(f.read())
f.close()

一般來(lái)講每窖,各種編碼都兼容ASII碼
各種編碼都是二進(jìn)制字節(jié)流去根據(jù)各自編碼表對(duì)應(yīng)不同的字符;二進(jìn)制字節(jié)流本身都是ASII碼弦悉。

+

+ 為r,w,a,x提供缺失的讀寫功能窒典,但是,獲取文件對(duì)象依舊按照r,w,a,x自己的特征稽莉。
+ 不能單獨(dú)使用瀑志,可以認(rèn)為它是為前面的模式字符做增強(qiáng)功能。

03-文件指針

文件指針:指向當(dāng)前字節(jié)位置
mode=r污秆,指針起始位置在0
mpde=a,指針起始位置在EOF
tell()顯示指針當(dāng)前位置
seek(offset[,whence]):移動(dòng)指針位置劈猪。offset偏移多少字節(jié),whence從哪里開(kāi)始混狠。
tell()和seek()都是針對(duì)字節(jié)的偏移岸霹,所以用他們處理字符流有風(fēng)險(xiǎn)

文本模式下:

  • whence 0 缺省值,表示從頭開(kāi)始将饺,offset只能接受0和正整數(shù)
  • whence 1 表示從當(dāng)前位置贡避,offset只接受0痛黎,相當(dāng)于原地不動(dòng),所以沒(méi)什么用
  • whence 2 表示EOF開(kāi)始刮吧,offset只接受0湖饱,相當(dāng)于移動(dòng)文件指針到EOF。
  • seek是按照字節(jié)偏移的杀捻。
  • 文本模式下只支持從開(kāi)頭向后偏移的方式

二進(jìn)制模式下

  • whence 0缺省值井厌,表示從頭開(kāi)始,offset只能是正整數(shù)致讥,包括0
  • whence 1表示從當(dāng)前位置仅仆,offset可正可負(fù)
  • whence 2表示從EOF開(kāi)始,offset可正可負(fù)
  • 二進(jìn)制模式支持任意起點(diǎn)的偏移垢袱,從頭墓拜,從尾,從中間位置開(kāi)始请契。
  • 向后seek可以超界咳榜,但是向前seek的時(shí)候,不能超界爽锥,否則會(huì)拋異常涌韩。

linux 下刪除一個(gè)文件的原理是將該文件的inode扔出去,讓別的文件使用氯夷,從而覆蓋掉改文件臣樱。
inode:索引節(jié)點(diǎn),它用來(lái)存放檔案及目錄的基本信息肠槽,包含時(shí)間擎淤、檔名、使用者及群組等秸仙。
04-緩沖區(qū)原理
緩存和緩沖的區(qū)別:
緩存:數(shù)據(jù)結(jié)構(gòu)為dict嘴拢,目的是快速找到想要的內(nèi)容
緩沖:數(shù)據(jù)結(jié)構(gòu)為list,一堆數(shù)據(jù)排隊(duì)放在那

04-緩沖區(qū)原理

buffering:緩沖區(qū)

  • open的一個(gè)參數(shù)
  • -1 表示使用缺省大小的buffer寂纪。
    • 如果是二進(jìn)制模式席吴,使用io.DEFAULT_BUFFER_SIZE值,默認(rèn)是4096或者8192,目前多是8192 個(gè)字節(jié)捞蛋。
    • 如果是文本模式:
      • 如果是終端設(shè)備孝冒,是 行緩存方式
      • 如果不是,則使用二進(jìn)制模式的策略拟杉。
  • 0 只在二進(jìn)制模式使用庄涡,表示關(guān)閉buffer,即不需要內(nèi)存buffer搬设,可以看做是一個(gè)FIFO的文件穴店。
  • 1 只在文本模式使用撕捍,表示使用行緩沖。意思是見(jiàn)到換行符就flush
  • 大于1 用于指定buffer的大衅础忧风;但是在文本模式下,通過(guò)實(shí)驗(yàn)發(fā)現(xiàn)還是在用buffer的默認(rèn)值球凰。

buffer緩沖區(qū)

緩沖區(qū)是內(nèi)存中的一個(gè)連續(xù)的空間狮腿,一般來(lái)說(shuō)是一個(gè)FIFO(先進(jìn)先出)隊(duì)列(不支持中間插入,只支持兩頭操作)呕诉,到緩沖區(qū)滿了或者達(dá)到閾值缘厢,數(shù)據(jù)才會(huì)flush到磁盤。
內(nèi)存的運(yùn)行速度比I/O設(shè)備高的多
flush()將緩沖區(qū)的數(shù)據(jù)寫入磁盤
close()關(guān)閉前會(huì)調(diào)用flush()
內(nèi)存的東西不是能直接寫到磁盤上去的义钉,從內(nèi)存空間的用戶空間昧绣,搬到操作系的內(nèi)核空間,從內(nèi)核空間寫到磁盤緩沖區(qū)里捶闸,由磁盤緩沖區(qū)寫入磁盤

buffering 總結(jié)

image.png

一般說(shuō)來(lái)只需記得:

  • 文本模式,一般都用默認(rèn)緩沖區(qū)大小
  • 二進(jìn)制模式拖刃,是一個(gè)個(gè)字節(jié)的操作删壮,可以指定buffer的大小
  • 一般來(lái)說(shuō),默認(rèn)緩沖區(qū)大小是個(gè)比較好的選擇兑牡,除非明確知道央碟,否則不調(diào)整它。
  • 一般編程中均函,明確知道需要寫磁盤了亿虽,都會(huì)手動(dòng)調(diào)用一次flush(f.flash()),而不是等到自動(dòng)flush或者close的時(shí)候苞也。

05-編碼描述符及讀寫方法

encoding:編碼洛勉,僅文本模式使用

None表示使用缺省編碼,依賴操作系統(tǒng)如迟,windows下缺省GBK,linux下缺省UTF-8
UTF-8:用多個(gè)字節(jié)編碼世界上的所有文字收毫;大多數(shù)中文落在3個(gè)字節(jié)上
UTF-8(8-bit Unicode Transformation Format)是一種針對(duì)Unicode的可變長(zhǎng)度字符編碼,也是一種前綴碼殷勘,又稱萬(wàn)國(guó)碼此再。
GBK:?jiǎn)巫止?jié)+雙字節(jié)。ASCII單字節(jié)玲销,中文雙字節(jié)输拇;CODEPAGE=936 ,代表GBK

image.png

跨平臺(tái)的時(shí)候建議用UTF-8
GBK和UTF-8之間編碼不一致贤斜,需要查表

其他參數(shù)

errors

什么樣的編碼錯(cuò)誤將被捕獲
None和strict表示編碼錯(cuò)誤將拋出ValueError異常策吠;ignore表示忽略议慰。
一般都用默認(rèn),不用管奴曙。

newline

文本模式中換行的轉(zhuǎn)換别凹。可以為None,"空串洽糟、'\r'炉菲、'\n'、'\r\n'
讀時(shí)坤溃,None表示'\r'屯断、'\n'、'\r\n'都被轉(zhuǎn)換為'\n'
寫時(shí)卸耘,None表示'\n'都會(huì)被替換為系統(tǒng)卻省行分隔符os.linesep敞掘;

f = open("D:/magedu/test",'w')
f.write('py\rwww\nmaedu\r\npython3')
f.close()

newlines = [None,'','\n','\r\n']
for nl in newlines:
    f = open("D:/magedu/test",'r+',newline=nl)
    #print(f.readlines())
    print(f.read().encode()) #通過(guò)編碼可以將換行符保留,而不是直接去做換行
    f.close()

closefd

關(guān)閉文件描述符汁政,True表示關(guān)閉它道偷。False會(huì)在文件關(guān)閉后保持這個(gè)描述符。
fileobject.fileno()查看记劈。

f = open("D:/magedu/test",'w')
print(f.fileno())  #文件描述符

文件打開(kāi)時(shí)就會(huì)產(chǎn)生一個(gè)文件對(duì)象勺鸦。

read

read(size=-1)
size表示讀取的多少個(gè)字符或字節(jié);負(fù)數(shù)或者None表示讀取到EOF

f = open("D:/magedu/test",'w')
f.write('python\r\n123\r\npython3')
f.close()

f = open("D:/magedu/test",'r+')
print(f.read().encode()) #指針到最后
f.seek(0)  #文件指針回到開(kāi)頭
print(f.readline(1).encode()) #一個(gè)個(gè)字符讀
f.close()

#以后讀取文件的每一行可以按照如下的讀目木,可以少寫一行
f = open("D:/magedu/test",'r')
for line in f:
    print(line)

write

write(s),把字符串s寫入到文件中并返回字符的個(gè)數(shù)换途;常用
writelines(lines),將字符串列表寫入文件
要自己提供換行符

close

flush并關(guān)閉文件對(duì)象
文件已經(jīng)關(guān)閉,再次關(guān)閉沒(méi)有任何效果

其他

seekable() :是否可seek
readable():是否可讀
writable():是否可寫
closed 是否已經(jīng)關(guān)閉

f = open("D:/magedu/test",'r')
print(f.seekable())  # True
print(f.readable()) # True
print(f.writable()) # False
print(f.closed)    # False
for line in f:
    print(line)
f.close()
print(f.closed)  # True

06-上下文管理

問(wèn)題的引出

在linux中執(zhí)行如下代碼:

lst = []
for _ in range(2000):
    lst.append(open('test')) 
#OSError:[Errorno 24] Too many open files:'test'
print(len(list))

lsof 列出打開(kāi)的文件刽射。沒(méi)有就 # yum install lsof
$lsof -p 1427|grep test|wc -l
lsof -p 進(jìn)程號(hào)
ulimit -a 查看所有限制军拟。其中open files 就是打開(kāi)文件數(shù)的限制,默認(rèn)1024

15分
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末誓禁,一起剝皮案震驚了整個(gè)濱河市懈息,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌现横,老刑警劉巖漓拾,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異戒祠,居然都是意外死亡骇两,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門姜盈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)低千,“玉大人,你說(shuō)我怎么就攤上這事∈狙” “怎么了棋傍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)难审。 經(jīng)常有香客問(wèn)我瘫拣,道長(zhǎng),這世上最難降的妖魔是什么告喊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任麸拄,我火速辦了婚禮,結(jié)果婚禮上黔姜,老公的妹妹穿的比我還像新娘拢切。我一直安慰自己,他們只是感情好秆吵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布淮椰。 她就那樣靜靜地躺著,像睡著了一般纳寂。 火紅的嫁衣襯著肌膚如雪主穗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天烈疚,我揣著相機(jī)與錄音黔牵,去河邊找鬼。 笑死爷肝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陆错。 我是一名探鬼主播灯抛,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼音瓷!你這毒婦竟也來(lái)了对嚼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绳慎,失蹤者是張志新(化名)和其女友劉穎纵竖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體杏愤,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡靡砌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珊楼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片通殃。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厕宗,靈堂內(nèi)的尸體忽然破棺而出画舌,到底是詐尸還是另有隱情堕担,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布曲聂,位于F島的核電站霹购,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朋腋。R本人自食惡果不足惜齐疙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乍丈。 院中可真熱鬧剂碴,春花似錦、人聲如沸轻专。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)请垛。三九已至催训,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宗收,已是汗流浹背漫拭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留混稽,地道東北人采驻。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像匈勋,于是被迫代替她去往敵國(guó)和親礼旅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容