1. 程式人生 > 實用技巧 >Python十一課--檔案和流

Python十一課--檔案和流

一.開啟檔案

1.開啟檔案可以使用open函式,返回一個file object,具體用法如下

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

這裡的file是一個用文字字串表示的檔名,如果檔案不在當前目錄下則需要給出其完整路徑
buffering控制檔案的緩衝,0表示無緩衝,1表示有緩衝,-1表示使用預設緩衝區大小
mode預設值為r,表示對檔案只做讀操作,mode 為w表示寫操作(不可讀;不存在則建立;存在則會清空原有檔案的內容)
mode 為x表示建立一個新檔案並執行寫操作(不可讀;檔案存在會丟擲異常)

mode 為a表示追加操作(可讀;不存在則建立;存在則只追加內容)
其餘引數的意義請參見幫助

2.如果需要開啟檔案c:\python\hello.txt,則可以:

>>> f = open(r'c:\python\hello.txt')

如果檔案不存在,則會得到如下提示:
Traceback (most recent call last):
File "<pyshell#93>", line 1, in <module>
f = open(r'c:\python\hello.txt')
FileNotFoundError: [Errno 2] No such file or directory: 'c:\\python\\hello.txt'


3.Python對開啟的是文字檔案還是二進位制檔案(例如聲音剪輯或者影象)進行區分,如果是二進位制檔案,則可以將引數b新增到其檔案開啟模式中使用
例如,使用mode=’rb’表示讀取一個二進位制檔案

引數+也可以用到其他任何模式中,表明讀和寫都是允許的,例如,r+ 模式(讀,追加模式)

>>> f = open('c:\python\hello.txt','r+',encoding='utf-8')
>>> data = f.read()  # 讀出檔案中的內容
>>> print(data)
The aircraft has yet to actually take off, 
but the company behind Stratolaunch says 
it
's expecting to perform a launch demonstration by "as early as 2019." >>> f.write("test...\n") 8 >>> print(f.read()) # 為什麼這裡的輸出是空的?見下 >>> f.tell() # 獲取檔案游標的現有位置 170 >>> f.seek(0) # 將檔案游標挪至檔案開頭 0 >>> print(f.read()) The aircraft has yet to actually take off, but the company behind Stratolaunch says it's expecting to perform a launch demonstration by "as early as 2019."test...

二.檔案的基本方法

1.讀和寫

(1.檔案(或流)最重要的能力是提供或者接收資料
(2.Python只能將字串寫入到文字檔案,要將數值資料儲存到文字本件中,必須先用內建函式str()將其轉換為字串格式
(3.如果有一個名為f的檔案物件,那麼可以用f.write方法和f.read方法(以字串形式)寫入和讀取資料

>>> f = open(r'c:\python\hello3.py', 'w’)

>>> f.write('Hello, ')
7                      # 返回寫入的位元組數
>>> f.write(‘world!’)  # 呼叫write方法時引數被追加到檔案尾
6

>>> f.close()         # 完成操作後需要呼叫close方法
執行完上面語句後,你會發現原來檔案中的內容被清空;如果確實是需要執行新增操作,則應將模式mode設為’a’


讀取的時候告訴流需要讀取多少個字元即可
>>> f = open(r'c:\python\hello3.py', 'r')
>>> f.read(5)              # 讀取5個字元
'Hello'
>>> f.read()            # 讀取剩餘內容
', world!'
>>> f.close()
如果僅對檔案內容進行讀取,則無需指定開啟模式,因為預設值為r

2.管道輸出

(1.:在Unix的shell中典型的管道(pipeline)輸出命令形式為
cat somefile.txt | python somescript.py
cat somefile.txt把somefile.txt的內容寫到標準輸出(sys.stdout)
python somecript.py 執行指令碼,從標準輸入中讀取資料並將結果寫到標準輸出中
(2. 管道符號(|)的作用是將一個命令的標準輸出和下一個命令的標準輸入連在一起,這樣形如
cat somefile.txt | python somescript.py
的命令會告訴somecript.py從sys.stdin中讀取資料(cat somefile.txt寫入的),並將結果寫入sys.stdout
(3.在Windows系統中安裝cygwin(http://cygwin.com,a large collection of GNU and Open Source tools which provide functionality similar to a Linux distribution on Windows),並執行上面的命令

(4.

假設有一個指令碼檔案somescript.py,內容如下:
# somescript.py
import sys
text = sys.stdin.read()
words = text.split()
wordcount = len(words)
print('Word count:', wordcount)

另外還有一個文字檔案somefile.txt:
Your mother was a hamster and your father smelled of elderberries.

以下是在cygwin環境中執行
cat somefile.txt | python somescript.py
命令的結果

注意:不使用管道輸出

# somescript.py

f = open('c:\python\somefile.txt', 'r')
data = f.read()
words = data.split()
wordcount = len(words)
print('Word count:', wordcount)

3.隨機訪問
(1.除了按照從頭到尾的順序讀取資料外(將檔案作為流來處理),在檔案中隨意移動讀取位置也是可以的
(2.使用檔案物件的seek和tell方法來直接訪問感興趣的部分,這種做法稱為隨機訪問
seek(offset[, whence])
offset是位元組(字元)數表示的偏移量
whence預設值為0,表示偏移量從檔案頭開始計算(文字檔案與二進位制檔案均適用);

如果是1表示相對當前位置的偏移;如果是2則表示相對檔案尾的偏移(僅適用於二進位制檔案)


考慮下面這個例子
>>> f = open(r'c:\python\hello.txt', 'w')
>>> f.write('01234567890123456789')
>>> f.seek(5)             # 把當前讀寫位置移動到第5個位元組處
>>> f.write(‘Hello, world!’) # 在當前位置寫入字串
>>> f.close()
>>> f = open(r'c:\python\hello.txt')
>>> f.read()
'01234Hello, world!89‘
* 注意:可以用help(io.IOBase.seek)檢視關於seek的幫助資訊

tell方法返回檔案當前的讀寫位置
>>> f = open(r'c:\python\hello.txt')
>>> f.read(3)
'012'
>>> f.read(4)
'34He'
>>> f.tell()
7

4.對行進行讀寫

(1.可以使用file.readline()讀取單獨的一行(從當前位置開始直到換行符出現
(2.也可以使用帶非負整數的引數作為可以讀取的位元組(或字元)的最大值,例如file.readline(5)
(3.使用file.readlines()方法則讀取一個檔案中所有行並將其作為列表返回,類似於fileinput.input()(返回FileInput類的物件)
(4.writelines方法和readlines方法正好相反:傳給它一個字串的列表(實際上任何序列和可迭代物件都行),它會將所有字串寫入檔案。另外,沒有writeline方法,可使用write方法寫入一行

>>> f = open(r'c:/python/fileinputoutput.txt', 'x')
>>> lst = ['This is the first line.', 'This is the second line.', 'And this is the third line.']
>>> f.writelines(lst)
>>> f.close()

如果指定檔案不存在則建立新檔案,顯示結果如下:
This is the first line.This is the second line.And this is the third line.
由此看來,程式不會自己增加新行,需要自己在每行後新增換行符,用於文字檔案中寫入時使用的行分隔符是’\n’

5.關閉檔案

(1.應該牢記在使用完檔案後呼叫close()進行關閉。寫入過的檔案總是應該關閉,是因為Python可能會快取寫入的資料;如果程式因為某些原因崩潰了,那麼資料就不會寫入檔案中
(2.為了確保關閉檔案,可以使用try/finally語句,並且在finally中呼叫close方法

f = open(r'c:/python/fileinputoutput.txt‘)
try# write data to your file
finally:
       f.close()

(3.事實上有專門為這種情況設計的語句,即使用with語句管理上下文

>>> with (open(r'c:/python/fileinputout.txt')) as somefile:
    do_something(somefile)

這裡with語句開啟檔案並將其賦值到變數somefile上,之後可以執行對檔案的其它操作,操作結束後文件會自動關閉,即使是由於異常引起的結束也是如此

在Python 2.7 後,with支援同時對多個檔案的上下文進行管理,即:    
with open('log1') as obj1, open('log2') as obj2:
pass 例如, >>> with open(r'c:/python/hello.txt', encoding = 'utf-8') as f1, open(r'c:/python/hello4.txt', encoding = 'utf-8') as f4: print(f1.read()) print(f4.read())

6.基本的檔案方法

(1.假設現在有一個文字檔案fileinputoutput.txt,其內容為
Welcome to this file
There is nothing here except
These three lines
然後我們使用檔案的各種讀寫方法

>>> f = open(r'c:/python/fileinputoutput.txt')
>>> f.read(7)   # 從檔案當前位置讀入7個位元組
'Welcome'
>>> f.read(4)
' to '
>>> f.close()


>>> f = open(r'c:/python/fileinputoutput.txt')
>>> print(f.read())   # 讀取檔案所有內容
Welcome to this file
There is nothing here except
These three lines
還可以使用readline()來讀取檔案所有內容
>>> f = open(r'c:/python/fileinputoutput.txt')
>>> for i in range(3):
    print(f.readline(), end=' ')

    
Welcome to this file
There is nothing here except
These three lines


試試readlines方法,將會讀取換行符
>>> import pprint
>>> pprint.pprint(open(r'c:\python\fileinputoutput.txt').readlines())
['Welcome to this file\n',
 'There is nothing here except\n',
 'These three lines']

7.寫檔案

使用write方法寫入一行或多行檔案內容
>>> f = open(r'c:\python\fileinputoutput.txt', 'w')
>>> f.write('This\n is\n another\nstring.')
25
>>> f.close()


使用writelines方法寫入多行檔案內容
>>> f = open(r'c:\python\fileinputoutput.txt', 'w’)
>>> lst = ['Welcome to this file\n', 'There is nothing here except\n', 'These three lines']
>>> f.writelines(lst)
>>> f.close()



三.對文章內容進行迭代