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表示追加操作(可读;不存在则创建;存在则只追加内容)注意: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()
三.对文件内容进行迭代
1.对文件内容进行迭代
对文件内容进行迭代以及重复执行一些操作,是最常见的文件操作之一
(1.例如可以在while循环中使用read方法,即对文件内容按字节处理
f = open(r'c:\python\fileinputoutput.txt') while True: char = f.read(1) if not char: break print(char) f.close()
(2.处理文本文件时还可以对文件的行进行迭代而不是处理单个字符,例如
f = open(r'c:\python\fileinputoutput.txt') while True: line = f.readline() if not line: break print(line) f.close()
2.读取文件所有内容
(1.如果文件不是很大,可以使用不带参数的read方法一次性读取整个文件
(2.或者还可以使用readlines方法,将文件读入一个字符串列表中,这时列表中每个元素就是文件中的一行
(3.需要注意的是,当文件尺寸非常大时,使用readlines方法会占用太多的内存。这时既可以用while和readline方法的组合来替代,也可以使用for和fileinput.input方法的组合
import fileinput >>> for line in fileinput.input(r'c:\python\fileinputoutput.txt'): print(line)
3.对行进行读取时的效率
(1.#对文件的第3行,做一个特殊的打印(这种方式比较低效,因为它会先把文件全部读取到内存中,文件较大时会对性能有很大影响)
>>> f = open('c:\python\hello.txt','r',encoding='utf-8') >>> for index,line in enumerate(f.readlines()): if index == 2: print('-------testing line------', line) print(line)
(2.#比较高效的,对文件的第3行进行特殊的打印,会一行一行去读取文件内容,不会一次性先把文件全部读取到内存中
>>> f = open('c:\python\hello.txt','r',encoding='utf-8') >>> count = 0 >>> for line in f: if count == 2: print('-------testing line------', line) count += 1 print(line)
4.文件迭代器
(1.由于文件对象是可迭代的,所以可以直接在for循环中使用它们,从而对其进行迭代
f = open(r'c:\python\fileinputoutput.txt') for line in f: print(line) f.close()
(2.需要注意的是,sys.stdin也是可迭代的
import sys for line in sys.stdin: s = reversed(line) if line == ‘\n’: break # 直接输入回车后跳出循环 print(list(s))
>>> f = open(r'c:\python\somefile.txt', 'x') >>> f.write('First line.\n') 12 >>> f.write('Second line.\n') 13 >>> f.write('Third line.\n') 12 >>> f.close() >>> lines = list(open(r‘c:\python\somefile.txt’)) # 将文件内容写入列表 >>> lines ['First line.\n', 'Second line.\n', 'Third line.\n'] >>> first, second, third = open(r‘c:\python\somefile.txt’) # 序列解包 >>> first 'First line.\n' >>> second 'Second line.\n' >>> third 'Third line.\n'
小结:
类文件对象:类文件对象是支持read、readline、readlines、write和writelines方法的对象
打开和关闭文件:提供一个文件名,可以使用open函数打开一个文件;如果希望确保文件被正常关闭,则可以使用with语句
模式和文件类型:打开文件时可以提供模式信息,’r’代表读模式,’w’代表写模式,也可以将文件以二进制文件形式打开
读和写:使用read或是write方法可以对文件对象进行读写操作
读写行:使用readline和readlines方法可以从文件中读取行,使用writelines语句则可以写入一行或多行数据
迭代文件内容:有很多方式可以迭代文件的内容。如果是迭代文本中的行,可以通过迭代文件对象本身来完成
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
打开文件file并返回文件对象