seek定位分析

语法:fileObject.seek(offset,whence)

  • offset:开始的偏移量,也就是代表需要移动偏移的字节数
  • whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0=文件开头,1=当前位置,2=文件末尾。
  • seek()与open()配合规则:①当seek(x,1&2)中,x≠0时,须用'b'模式open()文件,如:读取文件=open('file.txt','rb'),而写入文件除了open('file.txt','rb+'),入参须用b'str'模式,例如:fo.write(b'str')

cmd命令行下建一个纯净文件:echo ABCDEFG>a.txt

ABCDEFG


1.seek(offset,0)=指针指向文件对象起始位置

如何界定「seek(0)」? 它究竟是「第一个字符」还是「第一个字符之前的空字符」?

f=open('../a.txt','r')
f.seek(0)
print(f.tell()) # 0
print(f.readline()) #ABCDEFG

f.seek(1,0)
print(f.tell()) #1
print(f.readline()) #BCDEFG

f.seek(2,0)
print(f.tell()) #2
print(f.readline()) #CDEFG
# 通过本例我们得知:seek()指向哪位,我们就从哪位开始读取.

seek1

通过上面实验得:seek(0)使得指针指向「文本对象首位字符」的位置,而不是空位.
查阅了不少资料,并没有找到「.tell()返回值就是字符的序列号的权威解释,但用.tell()返回的数值作为字符的定位工具是很好的,我就暂时这么叫它了」


2.seek(offset,2)=指针指向文本对象末位

如何定义「末位」?
1.它究竟是「文本对象最后一个字符」还是「最后一个字符之后的空字符」?
2.究竟read()完毕后指针所在位是末尾?还是seek(0,2)才使指针指向末尾?
依然使用上例的文本 a.txt

ABCDEFG

#seek(offset,1&2)皆要使用'rb'模式打开.
# 首先用read()预览下文件,rb会将'\r\n'如实的显示出来,但它们只在你回车换行后会出现,如果文件没有回车换行过,就不会有'\r\n'出现.——这指的是单行状态,如果是多行:每次换行一定有'\r\n',但最尾部没有。(当然你也可以手贱非要在末尾回车一下而使我前面写的全白费.)
# 总之,'\r\n'是可以人为增加的,无甚定则,只要明白它的意思就好.

f=open("f:/work/a.txt","rb")
print(f.read()) #b'ABCDEFG\r\n'
print(f.tell()) #9 ,文件读取完毕,指针指向9,按'A=0位的规则',9位为空,并无字符.

f.seek(0,2) #强行将指针指向尾部
print(f.read()) #b'' ,得到的是空字符.
print(f.tell()) #9 

#从尾部逆向偏移1位,并在此处读取得到b'\n',说明:seek(-1,2)初始位是9(空),逆向移动一位到8.
f.seek(-1,2) 
print(f.tell()) #8
print(f.read()) # b'\n' 
f.close()

通过上述实验得知:不论read/readline/readlines操作还是seek(offset,2)操作,他们均非指向文本对象的末位,而是末位的下一个空位.
seek2
图中seek(0,2)指向9号空位.


总结:「读取指令」会读取指针指向位的字符,当读取完毕后,指针会自动跳到下一位待命,而不是待在已读取的最后一个字符位。(即:读取完就会跳到一位,跳到下一位才算读取完.)

  • 例如读取一个字符串,每读取一个字符后指针就会自动跳到下一个,直到依次读取完毕。
  • 例如:readline()会读取一行后,指针跳到下一行首位待命.[那么readline()之后执行tell()返回的就是下一行首位的位置.]
  • 例如:read()会读取全部字符后,指针跳到最后一个字符的下一个空位待命[那么read()/readlines()之后执行tell()返回的就是最后字符的下一个空位]

3.seek(offset,1)=指针目前所在位置

本次使用C文本:

ABCDE
abcde

f=open("f:/work/c.txt","rb")
print(f.read()) #b'ABCDE\r\nabcde'
print(f.tell()) #12

f.seek(2,1) #在当前位向后偏移2位
print(f.tell()) #14
print(f.read()) #b''
#虽然末位12之后是空字符,但依然可以读取出b'',不会报错

f.seek(-5,1)
print(f.tell()) #9
print(f.read()) #b'cde'

f.seek(-16,1)
print(f.tell())
print(f.read())
# 报错 OSError: [Errno 22] Invalid argument
#seek可以向后无限定位,但向前超出首位就会报错.
f.close()

PS:

  • seek()方法没有返回值。
  • 当有换行时,会被换行截断.
  • 如果文件使用“a”或“a+”模式打开进行附加,则在下一次写入时,任何seek()操作都将被撤销。
  • 如果仅使用'a'在附加模式下打开该文件,该方法基本上是无操作的,但是对于在启用读取(模式’a+‘)的附加模式下打开的文件,该方法仍然有用。
posted @ 2020-04-14 10:12  深藍  阅读(547)  评论(0编辑  收藏  举报