11.1 打开文件

open函数

open(name[,mode[,buffering]])

>>>f = open(r'C:\text\somefile.txt')


11.1.1 文件模式

open函数中模式参数的常用值

'r' 读模式   

'w' 写模式

'a' 追加模式

'b' 二进制模式

'+' 读/写模式


通过在模式参数中使用U参数能够在打开文件时使用通用的换行符支持模式,在这种模式下,所有的换行符/字符串(\r\n,\r或者是\n)都被转换成\n,而不用考虑运行的平台。


11.1.2 缓冲

open函数的第三个参数控制者文件的缓冲。如果参数是0或者False,I/O无缓冲的;如果是1或者True,就是有缓冲,大于1的数字代表缓冲区的大小,-1代表使用默认的缓冲区大小


11.2 基本文件方法

三种标准的流

数据输入得标准源是sys.stdin。

要打印的文本保存在sys.stdout内。

错误信息被写入sys.stderr.



11.2.1 读和写

文件最重要的能力是提供或者接受数据。如果一个名为f的类文件对象,那么就可以用f.write方法和f.read方法写入和读取数据。


每次调用f.write(string)时,所提供的参数string会被追加到文件中已存在部分的后面。

>>>f = open('somefile.txt','w')

>>>f.write('Hello, ')

>>>f.write('world!')

>>>f.close()


在完成了对一个文件的操作时,调用close。

例子:接上例:

>>>f = open('somefile.txt','r')

>>>f.read(4)

'Hello'

>>>f.read()

'o.World!'


首先指定了我要读取的字符数“4”,然后读取了剩下的文件。注意,在调用open时可以省略模式说明,因为'r'是默认的。


11.2.2 管式输出

$cat somefile.txt | python somescript.py | sort

somescript.py会从它的sys.stdin中读取数据(cat somefile.txt写入的),并把结果写入它的sys.stdout中。


统计sys.stdin中单词数的简单脚本

#somescript.py

import sys

text = sys.stdin.read()

words = text.split()

wordcount = len(words)

print 'Wordcount:',wordcount


可以用类文件对象seek和tell来直接访问感兴趣的部分(这种做法称为 随机访问)

seek(offset[,whence]):这个方法把当前位置移到由offest定义的位置。whence.offset是一个字节数,whence默认为0,也就是说偏移量是从文件开头开始计算的。whence可能被设置为1或者2


>>>f = open(r'c:\text\somefile.txt','w')

>>>f.write('01234567890123456789')

>>>f.seek(5)

>>>f.write('Hello,world!')

>>>f.close()

>>>f = open(r'c:\text\somefile.txt')

>>>f.read()

'01234Hello,world!89'


tell方法返回当前文件的位置如下:

>>>f = open(r'c:\text\somefile.txt')

>>>f.read(3)

'012'

>>>f.read(2)

'34'

>>>f.tell()

5L


11.2.3 读写行

逐个字符读取文件也是没问题的,进行逐行的读取也可以。还可以使用file.readline读取单独的一行。不使用任何参数或者使用一个非负的整数作为readline可以读取的字符的最大值。因此,如果someFile.readline()返回‘Hello,World!\n’,someFile.readline(5)返回‘Hello’。readlines方法可以读取一个文件中的所有行并将其作为列表返回。


writelines方法和readlines相反:传给它的一个字符串的列表,它会把所有的字符串写入文件。注意,程序不会增加新行,需要自己添加。没有writeline方法,因为能使用write。



11.2.3 关闭文件

如果想确保文件被关闭了,那么应该使用try/finally语句,并且在finally子句中调用close方法。

#Open your file here

try:

#Write data to your file

finally:

file.close()

事实上,有专门为这种情况设计的语句,with语句:

with open("somefile.txt") as somefile:

do_something(somefile)

with语句可以打开文件并且将其赋值到变量上。之后就可以将数据写入语句体中的文件。文件在语句结束后会被自动关闭,即使是由于异常引起的结束也是如此。


在python 2.5 中,with语句只有在导入如下的模块后才可以用:

from __future__ import with_statement


直到关闭文件才会写入文件。如果想继续使用文件,又想将磁盘上的文件进行更新,以反映这些修改,那么需要调用文件对象的flush方法。


上下文管理器

with语句实际上是很通用的结构,允许使用所谓的上下文管理器。上下文管理器是一种支持__enter__ 和__exit__ 方法的对象。


__enter__方法不带参数,它在进入with语句块的时候被调用,返回值绑定到在as关键字之后的变量。

__exit__方法带有3个参数:异常类型、异常对象和异常回溯。在离开方法时这个函数被调用。如果__exit__返回false,那么所有的异常都不会被处理。它们的__enter__方法返回文件对象本身,__exit__方法关闭文件。


11.2.5 使用基本文件方法

一个简单文本文件

Welcome to this file

There is nothing here except

This stupid haiku


首先是read(n):

>>>f = open(r'c:\text\somefile.txt')

>>>f.read(7)

'Welcome'

>>>f.read(4)

'to'

>>>f.close()


然后是read():

>>>f = open(r'c:\text\somefile.txt')

>>>print f.read()

Welcome to this file

There is nothing here except

This stupid haiku

>>>f.close()


接着是readline():

>>>f = open(r'c:\text\somefile.txt')

>>>for i in range(3):

print str(i) + ': ' + f.readline(),

0:Welcome to this file

1:There is nothing here except

2:This stupid haiku

>>>f.close()


以及readlines():

>>import pprint

>>>pprint.pprint(opne(r'c:\text\somefile.txt').readlines())

['Welcome to this file\n'

'There is nothing here except\n'

'This stupid haiku']

注意,本例中我所使用的是文件对象自动关闭的方式。

下面是写文件,首先是write(string):

>>>f = open(r'c:\text\somefile.txt','w')

>>>f.write('this\nis no\nhaiku')

>>>f.close()

运行后:

this

is no

haiku


最后是writelines(list):

>>>f = open(r'c:\text\somefile.txt')

>>>lines = f.readlines()

>>>f.close()

>>>line[1] = "isn't a\n"

>>>f = open(r'c:\text\somefile.txt','w')

>>>f.writelines(lines)

>>>f.close()

运行后:

this

isn't a

haiku


11.3.1 按字节处理

最常见的对文件内容进行迭代的方法是while循环中使用read方法。例如,对每个字符进行循环。

用read方法对每个字符进行循环

f = open(filename)

char = f.read(1)

while char:

process(char)

char = f.read(1)

f.close()

这个程序可以使用是因为当到达文件的末尾时,read方法返回一个空的字符串,但在那之前返回的字符串包含一个字符,如果char是真,则表示还没有到文件末尾。

可以看到,赋值语句char = f.read(1)被重复地使用,代码重复通常被认为是一件坏事。


用不同的方式写循环

f = open(filename)

while True:

char = f.read(1)

if not char:break

process(char)

f.close()


11.3.2 按行操作

当处理文本文件时,经常会对文件的行进行迭代而不是处理单个字符。处理行使用的方法和处理字符一样,即使用readline方法:

在while循环中使用readline

f = opne(filename)

while True;

line = f.readline()

if not line: break

process(line)

f.close()


11.3.3 读取所有内容

如果文件不是很大,那么可以使用不带参数的read方法一次读取整个文件,或者使用readlines方法。

用read迭代每个字符

f = open(filename)

for char in f.read()

process(char)

f.close()


用readlines迭代行

f = open(filename)

for line in f.readlines():

process(line)

f.close()


11.3.4使用fileinput实现懒惰行迭代

在需要对一个非常大的文件进行迭代行的操作时,readlines会占用太多的内存。这个时候可以使用while循环和readline方法来替代。当然,在python中如果能使用for循环,那么它就是首选。本例恰好可以使用for循环可以使用一个名为懒惰行迭代的方法:说它懒惰是因为它只是读取实际需要的文件部分。

用fileinput来对行进行迭代

import fileinput

for line in fileinput.input(filename):

process(line)


11.3.5 文件迭代器

迭代文件

f = open(filename)

for line in f:

process(line)

f.close()


对文件进行迭代而不使用变量存储文件对象

for line in open(filename)

process(line)

注意sys.stdin是可迭代的,就像其他的文件对象。因此如果想要迭代标准输入中的所有行,可以按如下形式使用sys.stdin.

import sys

for line in sys.stdin:

process(line)

可以对文件迭代器执行和普通迭代器相同的操作。比如将它们转换为字符串列表(使用list(open(filename)) ),这样所达到的效果和使用readlines一样。

>>>f = open('somefile.txt','w')

>>>f.write('First line\n')

>>>f.write('Second line\n')

>>>f.write('Third line\n')

>>>f.close()

>>>lines = list(open('somefile.txt'))

>>>lines

['First line\n','Second line\n','Third line\n']

>>>first,second,third = open('somefile.txt')

>>>first

'First line\n'

>>>second

'Second line\n'

>>>third

'Third line\n'

在这个例子中,有几点重要的:

1.使用print来向文件内写入内容,,这会在提供的字符串后面增加新的行

2.使用序列来对一个打开的文件进行解包操作,把每行都放入一个单独的变量中(这么做是很有实用性的,因为一般不知道文件中有多少行,但它演示了文件对象的“迭代性”)

3.在写文件后关闭了文件,是为了确保数据被更新到硬盘。