文件處理

一 文件操做

注操做文件的流程:python

#1. 打開文件,獲得文件句柄並賦值給一個變量
#2. 經過句柄對文件進行操做
#3. 關閉文件

 f=open('a.txt','r')的過程分析linux

#一、由應用程序向操做系統發起系統調用open(...)

#二、操做系統打開該文件,並返回一個文件句柄給應用程序

#三、應用程序將文件句柄賦值給變量f

強調!!!vim

#強調第一點:
打開一個文件包含兩部分資源:操做系統級打開的文件+應用程序的變量。在操做完畢一個文件時,必須把與該文件的這兩部分資源一個不落地回收,回收方法爲:
一、f.close() #回收操做系統級打開的文件
二、del f #回收應用程序級的變量

其中del f必定要發生在f.close()以後,不然就會致使操做系統打開的文件尚未關閉,白白佔用資源,
而python自動的垃圾回收機制決定了咱們無需考慮del f,這就要求咱們,在操做完畢文件後,必定要記住f.close()

雖然我這麼說,可是不少同窗仍是會很不要臉地忘記f.close(),對於這些不長腦子的同窗,咱們推薦傻瓜式操做方式:使用with關鍵字來幫咱們管理上下文
with open('a.txt','w') as f:
    pass
 
with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
    data=read_f.read()
    write_f.write(data)

強調第一點:資源回收
#強調第二點:
f=open(...)是由操做系統打開文件,那麼若是咱們沒有爲open指定編碼,那麼打開文件的默認編碼很明顯是操做系統說了算了,操做系統會用本身的默認編碼去打開文件,在windows下是gbk,在linux下是utf-8。
這就用到了上節課講的字符編碼的知識:若要保證不亂碼,文件以什麼方式存的,就要以什麼方式打開。

f=open('a.txt','r',encoding='utf-8')

python2中的file與openwindows

#首先在python3中操做文件只有一種選擇,那就是open()

#而在python2中則有兩種方式:file()與open()
二者都可以打開文件,對文件進行操做,也具備類似的用法和參數,可是,這兩種文件打開方式有本質的區別,file爲文件類,用file()來打開文件,至關於這是在構造文件類,而用open()打開文件,是用python的內建函數來操做,咱們通常使用open()打開文件進行操做,而用file當作一個類型,好比type(f) is file

 

 

二 打開文件的模式

文件句柄 = open('文件路徑', '模式')


#1. 打開文件的模式有(默認爲文本模式):
r ,只讀模式【默認模式,文件必須存在,不存在則拋出異常】
w,只寫模式【不可讀;不存在則建立;存在則清空內容】
a, 之追加寫模式【不可讀;不存在則建立;存在則只追加內容】

#2. 對於非文本文件,咱們只能使用b模式,"b"表示以字節的方式操做(而全部文件也都是以字節的形式存儲的,使用這種模式無需考慮文本文件的字符編碼、圖片文件的jgp格式、視頻文件的avi格式)
rb 
wb
ab
注:以b方式打開時,讀取到的內容是字節類型,寫入時也須要提供字節類型,不能指定編碼

#3. 瞭解部分
"+" 表示能夠同時讀寫某個文件
r+, 讀寫【可讀,可寫】
w+,寫讀【可讀,可寫】
a+, 寫讀【可讀,可寫】


x, 只寫模式【不可讀;不存在則建立,存在則報錯】
x+ ,寫讀【可讀,可寫】
xb

 

三 操做文件方法

#掌握
f.read() #讀取全部內容,光標移動到文件末尾
f.readline() #讀取一行內容,光標移動到第二行首部
f.readlines() #讀取每一行內容,存放於列表中

f.write('1111\n222\n') #針對文本模式的寫,須要本身寫換行符
f.write('1111\n222\n'.encode('utf-8')) #針對b模式的寫,須要本身寫換行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式

#瞭解
f.readable() #文件是否可讀
f.writable() #文件是否可讀
f.closed #文件是否關閉
f.encoding #若是文件打開模式爲b,則沒有該屬性
f.flush() #馬上將文件內容從內存刷到硬盤
f.name

四 文件內光標移動

一: read(3):

  1. 文件打開方式爲文本模式時,表明讀取3個字符

  2. 文件打開方式爲b模式時,表明讀取3個字節

二: 其他的文件內光標移動都是以字節爲單位如seek,tell,truncate

注意:

  1. seek有三種移動方式0,1,2,其中1和2必須在b模式下進行,但不管哪一種模式,都是以bytes爲單位移動的

  2. truncate是截斷文件,因此文件的打開方式必須可寫,可是不能用w或w+等方式打開,由於那樣直接清空文件了,因此truncate要在r+或a或a+等模式下測試效果
    
  剛打開文件就調用它會清空文件。

五 文件的修改

文件的數據是存放於硬盤上的,於是只存在覆蓋、不存在修改這麼一說,咱們平時看到的修改文件,都是模擬出來的效果,具體的說有兩種實現方式:編輯器

方式一:將硬盤存放的該文件的內容所有加載到內存,在內存中是能夠修改的,修改完畢後,再由內存覆蓋到硬盤(word,vim,nodpad++等編輯器)函數

 

import os

with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
    data=read_f.read() #所有讀入內存,若是文件很大,會很卡
    data=data.replace('alex','SB') #在內存中完成修改

    write_f.write(data) #一次性寫入新文件

os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

方式二:將硬盤存放的該文件的內容一行一行地讀入內存,修改完畢就寫入新文件,最後用新文件覆蓋源文件測試

 

import os

with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
    for line in read_f:
        line=line.replace('alex','SB')
        write_f.write(line)

os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

 

六 本身的一些收集

linux上處理windows上的文件時最好用 rb wb,還有進行文件傳輸的時候也要用b(二進制),避免 編碼方式的不一樣致使錯誤,並且文件中不止文本有圖片等的狀況會出錯.b模式跨平臺,由於全部系統存儲數據都是二進制.編碼

 

1.python 2.x中:
默認都是讀取文本文件,而且是ASCII編碼的文本文件。要讀取二進制文件,好比圖片、視頻等等,
用'rb'模式打開文件便可:

>>> f = open('/Users/michael/test.jpg', 'rb')
>>> f.read()
'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進制表示的字節

字符編碼:讀取非ASCII編碼的文本文件,就必須以二進制模式打開,再解碼。好比GBK編碼的文件:
>>> f = open('/Users/michael/gbk.txt', 'rb')
>>> u = f.read().decode('gbk') #將二進制解碼,存文件encode,讀取文件decode
>>> u
u'\u6d4b\u8bd5'
>>> print u
測試

 

6.1文件讀寫注意:文件寫入的是字符串,不能這樣

a = [1,2,3]
f.write(a)
不能f.write(5)

f = open(‘1.txt’,’w’,’buffersize’),其實跟file是同樣的,是file的別名。 文件打開的過程當中不能更改模式,除非r+或者w+模式。spa

 with open('1.txt','w','buffersize') as f:
     f.write('aaa')  #w模式不會自動換行,須要加上 \n,a 模式會自動加上\n
     f.writelines(['12\n''34\n'])
     f.close() #關閉文件,with模式下不用,會自動關閉。

     f.seek(-1,2), 從文件末尾爲原點計算,讀取倒數第一個字符
     f.read()
     f.readline()
     f.readlines() 讀取整個文件爲列表,將文件所有讀取到內存

     f.xreadlines() 一行一行讀取到內存中,處理大文件必需要用它,不要用readlines。
     f.write()
     f.writeline()
     f.truncate()  #截取文件,默認截取到當前位置。剛打開文件就調用它會清空文件。
     f.flush()  #將文件內存中的內容寫到磁盤

 注意:linux上處理windows上的文件時最好用 rb   wb,還有進行文件傳輸的時候也要用b(二進制),避免編碼方式的不一樣致使錯誤。


 f = file('1.txt','w')    #幫助  help(file),跟open是同樣的

操做方法同上


 f = file('test.txt','r')
 遍歷文件
     for line in f.xreadlines(): #大文件必須用xreadlines()一行一行讀
         print line,   #加上,  不打印換行符

 

6.2文件內容更改

fileinput模塊提供處理一個或多個文本文件的功能,能夠經過使用for循環來讀取一個或多個文本文件的全部行。

【默認格式】

    fileinput.input (files='filename', inplace=False, backup='', bufsize=0, mode='r', openhook=None)

    files:         #文件的路徑列表,默認是stdin方式,多文件['1.txt','2.txt',...]
    inplace:       #是否將標準輸出的結果寫回文件,默認不取代
    backup:        #備份文件的擴展名,只指定擴展名,如.bak。若是該文件的備份文件已存在,則會自動覆蓋。
    bufsize:       #緩衝區大小,默認爲0,若是文件很大,能夠修改此參數,通常默認便可
    mode:      #讀寫模式,默認爲只讀
    openhook:    #該鉤子用於控制打開的全部文件,好比說編碼方式等;

【經常使用函數】


    1 fileinput.input()       #返回可以用於for循環遍歷的對象
    2 fileinput.filename()    #返回當前文件的名稱
    3 fileinput.lineno()      #返回當前已經讀取的行的數量(或者序號)
    4 fileinput.filelineno()  #返回當前讀取的行的行號
    5 fileinput.isfirstline() #檢查當前行是不是文件的第一行
    6 fileinput.isstdin()     #判斷最後一行是否從stdin中讀取
    7 fileinput.close()       #關閉隊列

實例:替換Rain爲Jerry

    for line in fileinput.input('user.txt',backup='.bak',inplace=1):
        line = line.replace('Rain','Jerry')
        print line,

實例:向文件中指定位置插入內容操作系統

def file_insert(fname, str):
    r = ur'}'
    f = open(fname)
    old = f.read()
    num = int(re.search(r, old).start()) #正則找到要插入到的位置。

    f_input = fileinput.input(fname, inplace=1)
    #for line in fileinput.input(fname, inplace=1):
    for line in f_input:
        if r in line:
            print line.rstrip() #讓stdout被重定向到輸入文件裏
            print "\n"+str+"\n" #讓stdout被重定向到輸入文件裏,str是要插入的內容
            f.seek(num+2) #移動到插入位置末尾。
            print f.read() #讓stdout被重定向到輸入文件裏,將剩餘的內容打印
            break
        else:
            print line.rstrip()
    f.close()
    f_input.close()
    #print "OK! The %s configure has been sucessfull added!" % fname
    print "Ok! 配置文件%s已經添加成功!" % fname

注意: fileinput.input的inplace必需要設爲1,以便讓stdout被重定向到輸入文件裏。

6.3大文件迭代方法:

1.while + readline
f = open('text.txt',r)
while true:
    line = f.readline()  一行一行讀取,每讀取一行文件指針移動到下一行
    if line:
        pass
     else:
        break

2.xrandlines()

3.文本文件自帶的迭代:
f = open('text.txt',r)
for i in f:
    pass

4.用yield生成器。

6.4核心筆記:保留分行符

當使用輸入方法如read()或者readlines()從文件度取行時,python不會刪除結束符。文件寫操做同樣不會寫入 結束符號(n).

 

行分隔符和其它文件系統的差別:不一樣操做系統所支持的行分隔符,路徑分隔符,都不一樣。爲了有助於跨平臺開發, os模塊的如下屬性,在不一樣平臺會自動設置成相應的值。

>>> import os
>>> os.linesep
'\n'
>>> os.pathsep
':'
>>> os.sep
'/'
>>> os.curdir
'.'
>>> os.pardir
'..'
>>>

6.5標準文件: sys.stdin sys.stdout sys.stderr

標準輸入:通常是鍵盤。stdin對象爲解釋器提供輸入字符流,通常使用raw_input()和input()函數。 name = sys.stdin.readline() 至關於 raw_input()

標準輸出:通常是屏幕。stdout對象接收到print語句產生的輸出。 sys.stdout.write()方法其實就是上面所講的標準輸出,print語句就是調用了這個方法

錯誤輸出:通常是錯誤信息。stderr對象接收出錯的信息。

實例:從控制檯重定向到文件。

記住,若是你還想在控制檯打印一些東西的話,最好先將原始的控制檯對象引用保存下來, 向文件中打印以後再恢復 sys.stdout:

_console__ = sys.stdout #保存原始控制檯

import sys

f_handler=open('out.log', 'w')
sys.stdout=f_handler     #標準輸出重定向到文件
print 'hello'
print 'hello'
print 'hello'
f_handler.close()

sys.stdout= __console__  #恢復控制檯
print 'console'
相關文章
相關標籤/搜索