文件
■ 基本的文件用法
f = open("path","mode") mode有a,w,r,b,+等。默认为r。模式与打开文件时的动作有关系,比如用w打开的话肯定会清空文件再写,而a的话打开时就不会清空文件而是直接append内容
关于文件的打开模式,我有一句mmp一定要讲。。众所周知,在windows中换行符是 ,在unix中换行符是 ,而python做了一个事就是在一般的写模式下写文件的时候,自动根据当前的操作系统类型进行换行符的转换。这么一来有时候想要在windows下写完文件再传送到unix系统中就导致了这个文件再unix中不可直接调用。解决的方法就是把open("file","w")换成open("file","wb+"),加上b之后python就不知道写的文件是文本文件还是什么就不会轻易地做换行符的转换了。
f.read()/write(...)
f.close()
在很多示例中,打开文件用的都是这样一种方法:
with open("path","mode") as f:
f.操作
不用再手动关闭文件什么的,这个涉及到with这个上下文管理语句,现在还不是很懂,等以后有机会再来研究一下。
■ 读的方法
f.read(...) 读...个字符,无参数则读取整个文件
f.readline() 读取一行,如果有参数就是读取这行的前n个字符,每行包括换行符在内!
f.readlines() 读取一个由行组成的列表,每行也都有换行符
*因为程序是以流的形式读取文件的,所以在readline,read这种一点一点读取的方法里,读取完一部分后再读取就自动接续到下一部分了。
f.seek(offset[,whence]) seek方法指定文件读取指针位置。whence参数可选0,1或2分别代表文件开头,指针当前位置和文件结尾。offset设置一个数,可正可负,表示从whence设置的位置向前或向后偏移多少个字节开始读取文件内容。whence默认是0。因为可以重设指针位置,seek方法常用于文件流读取到一定程度后回过头再去读取或者跳过一部分内容读取、直接读取文件末尾部分等场景。比如f.seek(-128,2)的意思就是将文件读取指针设置到文件末尾前的128个字节处,之后再f.read()就可以直接读到文件最后128个字节的内容了。
■ 写的方法
f.write(...)
f.writelines([..,..,..]) 与readlines相反,用write将一个列表写进文件,注意的是writelines不会再每个元素后面自动加上换行回车,所以要手动地加上
■ 三个特别的类文件对象
stdin, stdout, stderr是sys的三个类文件对象,所谓类文件,就是说它们可以像一个文件一样去read和write,比如:
sys.stdin.readlines()
sys.stdout.write(...)
sys.stderr.write(...)
■ 对文件内容的遍历
● 按字节处理
用read(1)对字符做一个遍历,循环的条件可以是while char != ""来判断是不是把文件读完了
● 按行处理
用readline()对行做遍历,循环的条件可以是while line != ""。
需要注意的是readline每次只读一行,肯定效率比readlines要低一点,但是碰到很大的文件,没办法用readlines一次性读进内存的话,可以考虑用readline来遍历
● 更简便的写法
python中的文件是个可迭代的对象。这意味着我们也可以这么写:
for line in test_file:
process(line)
也就是说如果默认按照行来处理的话,甚至都可以不用写open来打开语句
■ 文件对象的flush方法
写入文件时,并不是调用一次write方法就马上写入的。可以试试看:
for i in range(5): sys.stdout.write("hello ") time.sleep(1)
会发现,这段代码要等5秒后才会把5行hello一起输出。这是因为调用write方法的时候先把待写入内容放入了缓存中。如果想要一秒就看到一条输出的话可以在sleep前面加上一个sys.stdout.flush()来清空缓存并写入内容。
说到这个顺便说一下,文件对象也会有很多自带的属性。flush是一个,其他还有一些比如
file.closed 返回布尔值,判断文件是否被关闭了
file.mode 返回文件被打开的方式
file.name 返回文件名
file.softspace 返回一个布尔值,如果是False就意味着文件在用print语句(或函数)进行输出的时候末尾会带一个空格符,一般不太用这个属性
■ 写入文件时的编码
在写入文件时,如果源数据是unicode格式的,那么在写入时python会自动用一个编码格式来把unicode编码再写入。然而这个编码格式往往就是ascii,这就导致了会有UnicodeEncodeError,为了解决这个问题,一个很好的办法就是在open文件的时候指定好编码。
网上有不少说builtin的open函数是带有encoding这个参数的,然而我试了下发现并不行。可以的方法是import codecs之后用codecs.open,这个方法的第三个参数是编码格式,就可以指定了。