5.2文件读写
Open()方法返回一个文件对象,在大多数情况下传递两个对象: open(filename, mode);
例如:
>>> f = open(’/tmp/workfile’, ’w’)
第一个参数是包含文件名称的字符串,第二个参数是包含描述文件使用方式的字符串。如果文件只读标记为“r”,只写标记为“w”(相同名字的已经存在文件将会被清除),, “a”表示添加到文件结尾,数据就会自动的添加到文件的结尾。“r+”表示可读可写。Mode参数是可选择的,如果没有此参数,默认表示可读的。
正常来说,文件会在text模式下打开,这就意味着你可以读写字符串到文件中,并且可以设置读写的编码格式(默认编码格式是utf-8).’b’表示用二进制的方式打开文件。这些数据将会用字节对象形式进行读写。这种模式可以用在所有的非文本格式文件中。
在文本格式中,默认的将平台特殊的换行结束符(在Unix是\n,在windos是\r\n)换成\n并在写入文件时转换回去。这是文件修改是无害的,但是在JPEG或者EXE文件中会破坏二进制数据。所以当读写这类文件时最好用二进制格式。
5.2.1 文件对象中方法
在这节所有的例子中假设一个名f的文件已创建。
为了读取文件的内容,调用f.read(size). 这个方法就能读取一定大小的数据并且返回一个字符串或者字节对象。Size是可选择的数字参数。当size缺少或者是负数,返回的就是整个文件内容。如果文件内容是你内存的两倍大,那就是你的问题了。不过,你应该尽可能大字节的读取文件内容,如果已经达到文件尾,f.read()将返回一个空字符串(“)、
>>> f.read()
’This is the entire file.\n’
>>> f.read()
’’
F.readline()就是从文件中读取单行,字符结尾会带一个新的字符“\n”,并且仅当在文件最后一行并没有换行符时才会省略。如果f.readline()会返回一个空字符串,则表示已经达到文件的末尾。当用“\n”表示一个空行时,将返回一个只含有一个换行符的字符串。
>>> f.readline()
’This is the first line of the file.\n’
>>> f.readline()
’Second line of the file\n’
>>> f.readline()
‘’
F.readlines()返回一个包含文件中多行数据的列表。如果传入一个可选择的sizehint,它就会从文件中读取至少包含指定字节数的完整行并返回之。这个方法通常用来高效地从大文件中逐行读取数据,而不会把整个所有文件内容加载到内存中。此方法只返回完整的文件行。
>>> f.readlines()
[’This is the first line of the file.\n’, ’Second line of the file\n’]
另一种可供选择读取多行的方法就是循环文件对象。这是一种内存高效,快速和并且代码简洁的方式。
>>> for line in f:
... print(line, end=’’)
...
This is the first line of the file.
Second line of the file
后一种方法虽然代码简洁但是不能提供更加细节控制能力,由于两个方法管理不同的行缓存,千万不要搞混。
F.write(String) 把字节内容写入到文件中,返回写入到文件的字符数量。
>>> f.write(’This is a test\n’)
15
除了写字符串也可以写入其他内容,但是必须首先转换为字符串。
>>> value = (’the answer’, 42)
>>> s = str(value)
>>> f.write(s)
18
F.tell()返回一个指文件对象在文件中的当前位置的整数。表示从文件开头到当前位置的字节数。想要改变文件对象的位置,用方法f.seek(offset, from_what). 位置是通过添加offset到参考点计算出来的。参考点通过from_what参数来选择。0 的from_what值意思就是从文件开头开始。值为1 时代表从当前文件位置开始计算,值为2时表示从文件为开始计算。From_what参数可以省略并且其默认值为0,即使用文件开头作为默认参考点。
>>> f = open(’/tmp/workfile’, ’rb+’)
>>> f.write(b’0123456789abcdef’)
16
>>> f.seek(5) # Go to the 6th byte in the file
5
>>> f.read(1)
b’5’
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
13
>>> f.read(1)
b’d’
在文本文件中(在字符串模式下用‘b’打开文件),仅仅婿从文件头开始计算相对位置(使用seek(0,2)从文件尾计算时就会引发异常)
当你使用一个文件时,调用方法f.close()来关闭它,然后释放任何被打开文件所占用的系统资源。在调用方法f.close()之后,试图再次调用文件对象就会自动失败。
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file
当处理文件对象时候,用with关键字是个很好的习惯。它有个益处: 在文件一系列操作结束后它就可以正确地关闭。从某种角度而言 异常也有值得表扬一面。它也比同等功能的try-finally 代码块更简洁。
>>> with open(’/tmp/workfile’, ’r’) as f:
... read_data = f.read()
>>> f.closed
True
文件对象有许多其他方法,例如isatty()和truncate(),这些方法相对使用的不太频繁。详细请查看库文件指导文档。
5.2.2 pickle模块
字符串很容易从文件中读写。数字则需要更多的处理,由于read()方法只能返回字符串,因此它不得不传给像int()函数,该方法能接受字符串“123”而返回数值123. 但是,当你想更复杂的数据类型时候,例如列表,字典或者类实例,这些变得更加复杂。
为了不让用户不同编码和调试代码来保存复杂数据类型,python提供了一个叫pickle的标准接口。这是一个能处理任何python对象的神奇模块。(甚至一些格式的python代码)。并且把它转化为字符串。这个过程叫做pickling(封装)。 从字符串形式来重建这个对象就成unpickling(拆封)。在拆封和封装过程中,表现对象的字符串形式会保存在文件或者数据中,或者通过网络连接发送给远程机器。
如果你有个对象x,和一个正在打开写的文件对象f,最简单封装对象的方法仅仅用一行代码:
pickle.dump(x, f)
如果f是一个正在读的文件对象,可用如下代码重构这个对象:
x = pickle.load(f)
(当封装许多对象时候或者当你不想写封装的数据到文件,这里还有其他方法,具体请咨询在python库文件引用有关pickle的完整文档。)
Pickle是一个来创建需要保存或者被其他程序或者同一个程序将来需要重新创建的python对象的标准方法。术语称为persistent对象(持久化对象)。Pickle模块被如此广泛的使用。许多python扩展开发者都非常注意像矩阵这样的新数据类型是否可以被适当的封装和拆封。