Python 为什么file_object.tell()为不同位置的文件提供相同的字节?
我刚刚开始学习python,无法绕过基本的文件导航方法 当我阅读教程时,它声明它返回我当前在文件中的位置(以字节为单位) 我的推理是,文件中的每个字符加起来就是字节坐标,对吗?这意味着在一个新行之后,这只是在Python 为什么file_object.tell()为不同位置的文件提供相同的字节?,python,python-2.7,Python,Python 2.7,我刚刚开始学习python,无法绕过基本的文件导航方法 当我阅读教程时,它声明它返回我当前在文件中的位置(以字节为单位) 我的推理是,文件中的每个字符加起来就是字节坐标,对吗?这意味着在一个新行之后,这只是在\n字符上拆分的一个字符串,我的字节坐标将改变。。。但这似乎是不正确的 我在bash上生成了一个快速玩具文本文件 $ for i in {1..10}; do echo "@ this is the "$i"th line" ; done > toy.txt $ for i in {1
\n
字符上拆分的一个字符串,我的字节坐标将改变。。。但这似乎是不正确的
我在bash上生成了一个快速玩具文本文件
$ for i in {1..10}; do echo "@ this is the "$i"th line" ; done > toy.txt
$ for i in {11..20}; do echo " this is the "$i"th line" ; done >> toy.txt
现在我将遍历这个文件并打印出行号和每个周期的tell()
调用的结果。@
用于标记一些分隔文件块的行,我想返回这些行(见下文)
我的猜测是for循环首先在file对象上迭代,到达它的末尾,因此它始终保持不变
这是一个很好的例子,在我真正的问题上,文件的长度是Gigs,通过应用相同的方法,我得到的结果是,tell()
在我的图像块中反映了for循环是如何在file对象上迭代的。
这是正确的吗?你能解释一下我所缺少的概念吗
我的最终目标是能够定位文件中的特定坐标,然后并行处理这些来自分布式起点的巨大文件,我无法以筛选它们的方式监视这些文件
os.path.getsize("toy.txt")
451
fa = open("toy.txt")
fa.seek(0) # let's double check
fa.tell()
count = 0
for line in fa:
if line.startswith("@"):
print line ,
print "tell {} count {}".format(fa.tell(), count)
else:
if count < 32775:
print line,
print "tell {} count {}".format(fa.tell(), count)
count += 1
迭代文件时,文件不一定位于循环锯的最后一个字符处。迭代文件时,文件不一定位于循环锯的最后一个字符处。您正在使用
for
循环逐行读取文件:
for line in fa:
文件通常不会这样做;您可以读取数据块,通常是数据块。为了让Python给您换行,您需要一直读到下一行。只是,逐字节读取以查找换行符不是很有效
因此使用了缓冲区;你读一个大段,然后在该段中找到换行符,并为找到的每一个换行符生成一行。缓冲区用完后,您将读取一个新块
您的文件大小不足以读取多个块;它只有451字节小,而缓冲区通常以千字节为单位。如果您要创建一个更大的文件,您将在迭代时看到文件位置以大步跳转
参见(next
是迭代时负责生成下一行的方法,for
循环所做的工作):
为了使for循环成为在文件行上循环的最有效方式(一种非常常见的操作),next()
方法使用隐藏的预读缓冲区
如果在行上循环时需要跟踪绝对文件位置,则必须在Windows上使用二进制模式If(以防止换行转换发生),并自己跟踪行长度:
position = 0
for line in fa:
position += len(line)
另一种选择是使用;这是Python3中用于处理文件的框架。file.tell()
方法将缓冲区考虑在内,即使在迭代时也会生成准确的文件位置
考虑到当您使用文本模式打开文件时,您将获得unicode
字符串。在Python2中,如果必须使用str
bytestrings,则可以使用二进制模式(用'rb'
打开)。事实上,只有在二进制模式下,您才能访问IOBase.tell()
,而在文本模式下会引发异常:
>>> import io
>>> fa = io.open("toy.txt")
>>> next(fa)
u'@ this is the 1th line\n'
>>> fa.tell()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: telling position disabled by next() call
您正在使用
for
循环逐行读取文件:
for line in fa:
文件通常不会这样做;您可以读取数据块,通常是数据块。为了让Python给您换行,您需要一直读到下一行。只是,逐字节读取以查找换行符不是很有效
因此使用了缓冲区;你读一个大段,然后在该段中找到换行符,并为找到的每一个换行符生成一行。缓冲区用完后,您将读取一个新块
您的文件大小不足以读取多个块;它只有451字节小,而缓冲区通常以千字节为单位。如果您要创建一个更大的文件,您将在迭代时看到文件位置以大步跳转
参见(next
是迭代时负责生成下一行的方法,for
循环所做的工作):
为了使for循环成为在文件行上循环的最有效方式(一种非常常见的操作),next()
方法使用隐藏的预读缓冲区
如果在行上循环时需要跟踪绝对文件位置,则必须在Windows上使用二进制模式If(以防止换行转换发生),并自己跟踪行长度:
position = 0
for line in fa:
position += len(line)
另一种选择是使用;这是Python3中用于处理文件的框架。file.tell()
方法将缓冲区考虑在内,即使在迭代时也会生成准确的文件位置
考虑到当您使用文本模式打开文件时,您将获得unicode
字符串。在Python2中,如果必须使用str
bytestrings,则可以使用二进制模式(用'rb'
打开)。事实上,只有在二进制模式下,您才能访问IOBase.tell()
,而在文本模式下会引发异常:
>>> import io
>>> fa = io.open("toy.txt")
>>> next(fa)
u'@ this is the 1th line\n'
>>> fa.tell()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: telling position disabled by next() call