2007-07-11
Python Cookbook 2.8 使用随机方式修改
需求:
要从一个大的二进制文件中读取 一块数据,修改完成后,要写回文件.
讨论:
打开文件,做必要的偏移计算,读取数据,处理完后,重新定位到数据偏移处,写入数据即可.看代码吧,比说的更清楚一些:
import struct
format_string = '8l' # e.g., say a record is 8 4-byte integers
thefile = open('somebinfile', 'r+b')
record_size = struct.calcsize(format_string)
thefile.seek(record_size * record_number)
buffer = thefile.read(record_size)
fields = list(struct.unpack(format_string, buffer))
# Perform computations, suitably modifying fields, then:
buffer = struct.pack(format_string, *fields)
thefile.seek(record_size * record_number)
thefile.write(buffer)
thefile.close( )
这种方式只有在二进制文件的数据块是固定大小的时候适用,对于一般的文本文件不适用,另外, 数据库的大小要和struct中定义的一样.代码中的struct的典型定义'8l',表示每一个字段是8个4字节的整数构成,它们都是有符号整数类型,被转换为Python的int型数据.这样,上面的代码中fields表示了8个整数为单位的列表.需要注意的是unpack返回的是一个元组,而元组是不可修改的,所以要将它重新绑定为一个列表,因为列表是可以修改的.但要注意的是,不要修改列表的大小,因为如果你要用struct.pack写回的时候 ,会抛出异常.同样,本节的方法也不适用于文件中数据块大小不固定的情况.
当再次定位文件指针的时候,可以不使用seek(record_size * record_number),而使用反向偏移定位:
thefile.seek(-record_size, 1)
其中第二个参数1表示从文件的当前位置开始定位,由于第一个参数是负值, 所以是向前定位了.seek默认是从文件的起始位置开始定位,当然你也可以显示的将第二个参数设置为0.
当你调用第一个seek之前,不必再次调用open打开文件,同样,也不用在调用完write方法后立刻close它.当你正确打开了文件对象(二进制更新模式,而不是文本模式),你可以任意次数的更新文件,最后再关闭.
文件需要以更新模式打开(同时支持读和写),这就是'r+b'的含义:为读和写操作打开文件,并且不做任何隐含的转换,因为是二进制模式的.('b'在Unix和类unix系统上是可选的,不过还是建议加上,当然,在windows系统是,是必须的),如果你只是想创建一个草稿文件,可是仍要做一些读写处理,可以使用'w+b' 做为open的第二个参数.当然,我从来没有见过这么奇怪的需求.二进制文件一般都是先被创建(使用'wb'参数,写数据,然后关闭),再用'r+b'参数打开处理.
当然,虽然本节提供的方法只适用于固定数据块大小的二进制文件,也可以适用于更高级的情况:有一个索引文件表示块的大小和位置,这种通过索引文件访问的技术已经不是什么新技术了,可是它还是非常重要的.在今天,虽然人们处理的情况大多数是数据库,文本文件(还包括html,xml等),还有偶尔的固定块大小的二进制文件, 也不能排出遇到使用索引文件的可能性.如果遇到这样的情况,处理的方法和本节是非常类似的,只是块大小和偏移位置不是计算的,而是从索引文件中读取的.
相关说明:
seek(...)
seek(offset[, whence]) -> None. Move to new file position.
Argument offset is a byte count. Optional argument whence defaults to
0 (offset from start of file, offset should be >= 0); other values are 1
(move relative to current position, positive or negative), and 2 (move
relative to end of file, usually negative, although many platforms allow
seeking beyond the end of a file). If the file is opened in text mode,
only offsets returned by tell() are legal. Use of other offsets causes
undefined behavior.
Note that not all file objects are seekable.
要从一个大的二进制文件中读取 一块数据,修改完成后,要写回文件.
讨论:
打开文件,做必要的偏移计算,读取数据,处理完后,重新定位到数据偏移处,写入数据即可.看代码吧,比说的更清楚一些:
import struct
format_string = '8l' # e.g., say a record is 8 4-byte integers
thefile = open('somebinfile', 'r+b')
record_size = struct.calcsize(format_string)
thefile.seek(record_size * record_number)
buffer = thefile.read(record_size)
fields = list(struct.unpack(format_string, buffer))
# Perform computations, suitably modifying fields, then:
buffer = struct.pack(format_string, *fields)
thefile.seek(record_size * record_number)
thefile.write(buffer)
thefile.close( )
这种方式只有在二进制文件的数据块是固定大小的时候适用,对于一般的文本文件不适用,另外, 数据库的大小要和struct中定义的一样.代码中的struct的典型定义'8l',表示每一个字段是8个4字节的整数构成,它们都是有符号整数类型,被转换为Python的int型数据.这样,上面的代码中fields表示了8个整数为单位的列表.需要注意的是unpack返回的是一个元组,而元组是不可修改的,所以要将它重新绑定为一个列表,因为列表是可以修改的.但要注意的是,不要修改列表的大小,因为如果你要用struct.pack写回的时候 ,会抛出异常.同样,本节的方法也不适用于文件中数据块大小不固定的情况.
当再次定位文件指针的时候,可以不使用seek(record_size * record_number),而使用反向偏移定位:
thefile.seek(-record_size, 1)
其中第二个参数1表示从文件的当前位置开始定位,由于第一个参数是负值, 所以是向前定位了.seek默认是从文件的起始位置开始定位,当然你也可以显示的将第二个参数设置为0.
当你调用第一个seek之前,不必再次调用open打开文件,同样,也不用在调用完write方法后立刻close它.当你正确打开了文件对象(二进制更新模式,而不是文本模式),你可以任意次数的更新文件,最后再关闭.
文件需要以更新模式打开(同时支持读和写),这就是'r+b'的含义:为读和写操作打开文件,并且不做任何隐含的转换,因为是二进制模式的.('b'在Unix和类unix系统上是可选的,不过还是建议加上,当然,在windows系统是,是必须的),如果你只是想创建一个草稿文件,可是仍要做一些读写处理,可以使用'w+b' 做为open的第二个参数.当然,我从来没有见过这么奇怪的需求.二进制文件一般都是先被创建(使用'wb'参数,写数据,然后关闭),再用'r+b'参数打开处理.
当然,虽然本节提供的方法只适用于固定数据块大小的二进制文件,也可以适用于更高级的情况:有一个索引文件表示块的大小和位置,这种通过索引文件访问的技术已经不是什么新技术了,可是它还是非常重要的.在今天,虽然人们处理的情况大多数是数据库,文本文件(还包括html,xml等),还有偶尔的固定块大小的二进制文件, 也不能排出遇到使用索引文件的可能性.如果遇到这样的情况,处理的方法和本节是非常类似的,只是块大小和偏移位置不是计算的,而是从索引文件中读取的.
相关说明:
seek(...)
seek(offset[, whence]) -> None. Move to new file position.
Argument offset is a byte count. Optional argument whence defaults to
0 (offset from start of file, offset should be >= 0); other values are 1
(move relative to current position, positive or negative), and 2 (move
relative to end of file, usually negative, although many platforms allow
seeking beyond the end of a file). If the file is opened in text mode,
only offsets returned by tell() are legal. Use of other offsets causes
undefined behavior.
Note that not all file objects are seekable.