如何确定文件是否处于“eof”状态?

How to find out whether a file is at its `eof`?

提问人:Alcott 提问时间:4/13/2012 更新时间:1/11/2022 访问量:512356

问:

fp = open("a.txt")
#do many things with fp

c = fp.read()
if c is None:
    print 'fp is at the eof'

除了上述方法之外,还有其他方法可以找出 fp 是否已经在 eof 上?

python 文件 eof

评论

6赞 Gareth Latty 4/13/2012
值得一看的是用于打开文件的 with 语句 - 它可以很好地为您处理关闭和异常,并且阅读良好。

答:

9赞 Lauritz V. Thaulow 4/13/2012 #1

您可以比较调用该方法之前和之后的返回值。如果它们返回相同的值,则 fp 位于 eof。fp.tell()read

此外,我认为您的示例代码实际上不起作用。据我所知,该方法永远不会返回,但它确实在 eof 上返回一个空字符串。readNone

评论

0赞 Andry 10/3/2019
例如,如果它处于迭代状态,则不能使用:fp.tell()OSError: telling position disabled by next() call
35赞 NPE 4/13/2012 #2

我认为从文件中读取是确定它是否包含更多数据的最可靠方法。它可能是一个管道,或者另一个进程可能正在将数据追加到文件中等。

如果您知道这不是问题,则可以使用类似以下内容:

f.tell() == os.fstat(f.fileno()).st_size

评论

0赞 krystan honour 4/13/2012
同意,如果你调用read()并且你在EOF它将返回''
7赞 Bruno Bronosky 3/28/2017
我更喜欢事前,然后事后再做。按照自己的方式做有优势吗?注意:我当然建议将大小缓存到变量中,而不是调用每个循环。fh.seek(0, 2); file_size = fh.tell(); fh.seek(0)fh.tell() == file_sizeos.fstat
4赞 rmalouf 5/20/2017
请注意,如果文件以文本模式打开,这将不起作用:以字符为单位提供文件位置,并以字节为单位提供文件长度。不过,@BrunoBronosky的方法会奏效。f.tell()os.fstat(f.fileno()).st_size
2赞 mensi 4/13/2012 #3

如果 Python 读取函数达到 EOF,它们将返回一个空字符串

92赞 Fred Foo 4/13/2012 #4

fp.read()读取到文件末尾,因此在成功完成后,您知道文件位于 EOF;无需检查。如果它无法到达 EOF,它将引发异常。

当以块而不是 的形式读取文件时,当返回的字节数小于请求的字节数时,您就知道您已经命中了 EOF。在这种情况下,以下调用将返回空字符串 (not )。以下循环以块形式读取文件;它最多会调用一次太多。read()readreadNoneread

assert n > 0
while True:
    chunk = fp.read(n)
    if chunk == '':
        break
    process(chunk)

或者,更短:

for chunk in iter(lambda: fp.read(n), ''):
    process(chunk)

评论

4赞 Alcott 4/13/2012
是的,你是对的。所以没有有效的方法来检查是否达到?eof
1赞 Fred Foo 4/13/2012
@Alcott:对于普通文件,有 AIX 的方法。当分块阅读时,比如说 ,当它返回的字符少于字符时,你就会知道你已经点击了 EOF。fp.read(n)n
3赞 Gareth Latty 4/13/2012
除非您有理由以块的形式处理文件,否则通常更自然地逐行处理它,python 提供了这一点,因为文件是迭代器 - 所以您可以直接操作并让 for 循环为您处理它。for line in file: ...
19赞 Quentin Pradet 5/2/2013
根据 BufferedIOBase 文档:“对于交互式原始流(tty/终端),短结果并不意味着 EOF 即将到来。
5赞 matrixanomaly 7/18/2015
@larsmans刚刚用了这个,谢谢!虽然我的是二进制流,但我应该在这里注意,它只适用于文字字符串流,二进制流需要,请注意额外的 b。if chunk == '':if chunk == b'':
8赞 01100110 4/13/2012 #5

遇到 EOF 时,read 返回一个空字符串。文档在这里

4赞 ymattw 9/10/2013 #6

如果文件在非块模式下打开,返回的字节数少于预期并不意味着它处于 eof,我会说 @NPE 的答案是最可靠的方法:

f.tell() == os.fstat(f.fileno()).st_size

63赞 BeepBoop 7/14/2014 #7

“for-else”设计经常被忽视。参见:Python 文档“控制循环中的流程”

with open('foobar.file', 'rb') as f:
    for line in f:
        foo()

    else:
        # No more lines to be read from file
        bar()

评论

50赞 Artyer 1/26/2018
从字面上看,这毫无意义.不写它,只是有相同的作品。 只有当你使用时才会有区别。else:bar()elsebreak
2赞 Jacob Bruinsma 9/29/2020
有人可能会读到这篇文章并关心:)我不知道你可以逐行迭代 f(即使在二进制模式下!我不喜欢其他:它没有意义,它只是添加了一行和更多的缩进代码。它的目的和行为令人困惑,就像 try/except 中的 finally 一样。
17赞 user545424 8/1/2014 #8

执行二进制 I/O 时,以下方法很有用:

while f.read(1):
    f.seek(-1,1)
    # whatever

优点是有时您正在处理二进制流,并且事先不知道需要读取多少内容。

评论

0赞 GreenAsJade 11/12/2014
这如何告诉你你是否在EOF?
0赞 user545424 11/13/2014
@GreenAsJade,将在 EOF 处返回空字符串。f.read(1)
0赞 GreenAsJade 11/13/2014
哼!和。。。寻求是必不可少的,而不仅仅是任何事物的一部分吗?它的作用是什么?
0赞 user545424 11/13/2014
当您使用并且文件不在 时,您只需读取一个字节,因此 告诉文件向后移动一个字节。f.read(1)EOFf.seek(-1,1)
1赞 user545424 9/1/2017
@Chris,据我所知,任何非空字符串的计算结果始终为 True。您可以通过运行 在解释器中检查这一点。bool('\0')
-5赞 A R 10/27/2014 #9

您可以使用以下代码片段逐行阅读,直到文件末尾:

line = obj.readline()
while(line != ''):
    # Do Something
    line = obj.readline()
9赞 samba 12/9/2014 #10
f=open(file_name)
for line in f:
   print line

评论

0赞 fcm 4/6/2019
非常蟒蛇,没有额外的测试
1赞 Lovethenakedgun 5/14/2019
使用而不是使用时,您还应该确保在完成后致电,否则可能会出现意想不到的副作用f = open(...)with open(...) as ff.close()
0赞 Blairg23 1/12/2016 #11

虽然我个人会使用语句来处理打开和关闭文件,但如果您必须从 stdin 读取并需要跟踪 EOF 异常,请执行如下操作:with

使用 try-catch 作为例外:EOFError

try:
    input_lines = ''
    for line in sys.stdin.readlines():
        input_lines += line             
except EOFError as e:
    print e
32赞 tingtong 6/16/2016 #12

由于 python 在 EOF 上返回空字符串,而不是“EOF”本身,因此您可以检查此处编写的代码

f1 = open("sample.txt")

while True:
    line = f1.readline()
    print line
    if ("" == line):
        print "file finished"
        break;

评论

14赞 Leonardo Raele 5/1/2020
文件中的空行会中断此算法。
19赞 randomdude999 9/3/2020
@LeonardoRaele:空行将导致返回 。仅当文件实际位于 EOF 时,它才会返回空字符串。readline"\n"
2赞 hochl 3/5/2021
为什么不呢?if not line: break
0赞 olejorgenb 7/2/2022
如果文件不以 a 结尾,我想在这种情况下会添加一个怎么办?(懒得检查atm.,但这个细节让API有点混乱。如果文档更清楚就好了)\nreadline()\n
1赞 BenMorel 7/12/2022
根据文档:f.readline() 从文件中读取一行; 换行符 (\n) 保留在字符串的末尾,如果文件不以换行符结尾,则仅在文件的最后一行省略。这使得返回值明确无误;如果 f.readline() 返回一个空字符串,则表示已到达文件末尾,而空行由“\n”表示,该字符串仅包含一个换行符。
0赞 Pedro Miguel Deseado 8/1/2016 #13

我使用这个功能:

# Returns True if End-Of-File is reached
def EOF(f):
    current_pos = f.tell()
    file_size = os.fstat(f.fileno()).st_size
    return current_pos >= file_size

评论

0赞 Papa Smurf 8/12/2016
我想你的意思是在最后一行中测试平等。
2赞 Newstein 7/31/2017 #14
f = open(filename,'r')
f.seek(-1,2)     # go to the file end.
eof = f.tell()   # get the end of file location
f.seek(0,0)      # go back to file beginning

while(f.tell() != eof):
    <body>

您可以使用文件方法 seek() 和 tell() 来确定文件末尾的位置。找到位置后,返回文件开头

评论

0赞 Noel Widmer 7/31/2017
你能通过编辑你的帖子来解释你的解决方案在做什么吗?仅发布代码通常是不够的。
1赞 wamba 1/28/2018 #15

你可以通过调用方法到达后使用方法,如下所示:tell()EOFreadlines()

fp=open('file_name','r')
lines=fp.readlines()
eof=fp.tell() # here we store the pointer
              # indicating the end of the file in eof
fp.seek(0) # we bring the cursor at the begining of the file
if eof != fp.tell(): # we check if the cursor
     do_something()  # reaches the end of the file

评论

0赞 Henry Crutcher 1/28/2018
你能格式化这篇文章吗——它似乎有一个难以阅读的代码片段,因为它的格式都在一行上。
9赞 mach6 2/8/2018 #16

我真的不明白为什么python仍然没有这样的功能。我也不同意使用以下内容

f.tell() == os.fstat(f.fileno()).st_size

主要原因是在某些特殊条件下不太可能起作用。f.tell()

对我有用的方法如下。如果您有一些类似以下的伪代码

while not EOF(f):
     line = f.readline()
     " do something with line"

您可以将其替换为:

lines = iter(f.readlines())
while True:
     try:
        line = next(lines)
        " do something with line"
     except StopIteration:
        break

此方法很简单,无需更改大部分代码。

1赞 boechat107 2/26/2018 #17

分批读取文件(最后一批可以更短):BATCH_SIZE

BATCH_SIZE = 1000  # lines

with open('/path/to/a/file') as fin:
    eof = False
    while eof is False:
        # We use an iterator to check later if it was fully realized. This
        # is a way to know if we reached the EOF.
        # NOTE: file.tell() can't be used with iterators.
        batch_range = iter(range(BATCH_SIZE))
        acc = [line for (_, line) in zip(batch_range, fin)]

        # DO SOMETHING WITH "acc"

        # If we still have something to iterate, we have read the whole
        # file.
        if any(batch_range):
            eof = True

评论

0赞 Jeff Tilton 5/6/2022
这是这个问题的最佳答案
1赞 Константин Ван 7/23/2018 #18

获取文件的 EOF 位置:

def get_eof_position(file_handle):
    original_position = file_handle.tell()
    eof_position = file_handle.seek(0, 2)
    file_handle.seek(original_position)
    return eof_position

并将其与当前位置进行比较:。get_eof_position == file_handle.tell()

4赞 Shital Shah 5/1/2019 #19

Python 没有内置的 eof 检测功能,但该功能可以通过两种方式获得:如果没有更多字节要读取,将返回。这适用于文本和二进制文件。第二种方法是用来查看当前寻道位置是否在末尾。如果您希望 EOF 测试不更改当前文件位置,那么您需要一些额外的代码。f.read(1)b''f.tell()

下面是这两种实现。

使用 tell() 方法

import os

def is_eof(f):
  cur = f.tell()    # save current position
  f.seek(0, os.SEEK_END)
  end = f.tell()    # find the size of file
  f.seek(cur, os.SEEK_SET)
  return cur == end

使用 read() 方法

def is_eof(f):
  s = f.read(1)
  if s != b'':    # restore position
    f.seek(-1, os.SEEK_CUR)
  return s == b''

如何使用它

while not is_eof(my_file):
    val = my_file.read(10)

玩这个代码

评论

0赞 hochl 3/5/2021
为什么不在?if s: f.seek( ... )# restore position
12赞 Daniel Mitchell 6/29/2020 #20

这是使用 Walrus Operator 执行此操作的方法(Python 3.8 中的新功能)

f = open("a.txt", "r")

while (c := f.read(n)):
    process(c)

f.close()

有用的 Python 文档 (3.8):

海象操作员:https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions

文件对象的方法:https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects

0赞 Xcalibur 8/4/2020 #21

此代码适用于 python 3 及更高版本

file=open("filename.txt")   
f=file.readlines()   #reads all lines from the file
EOF=-1   #represents end of file
temp=0
for k in range(len(f)-1,-1,-1):
    if temp==0:
        if f[k]=="\n":
            EOF=k
        else:
            temp+=1
print("Given file has",EOF,"lines")
file.close()
0赞 Nhat Nguyen Duc 1/8/2022 #22

您可以尝试以下代码:

import sys
sys.stdin = open('input.txt', 'r') # set std input to 'input.txt'

count_lines = 0
while True:
    try: 
        v = input() # if EOF, it will raise an error
        count_lines += 1
    except EOFError:
        print('EOF', count_lines) # print numbers of lines in file
        break

评论

1赞 Sercan 1/11/2022
说明您希望尝试此代码的原因。