如何找出文件是否位于其“ eof”上?


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

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

除上述方法外,还有其他方法可以找出fp是否已达到eof?


5
值得一看的是打开文件的with语句-它可以为您很好地处理关闭和异常,并且读起来也不错。
Gareth Latty

Answers:


68

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

当分块读取文件而不是用读取文件时read(),您知道当read返回的字节数少于您请求的字节数时,您遇到了EOF 。在这种情况下,以下read调用将返回空字符串(不是None)。以下循环读取大块文件;read最多只会调用一次。

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

或者,更短:

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

3
你是对的。因此,没有有效的方法来检查是否eof达到?
Alcott

1
@Alcott:普通文件有aix的方法。当分块阅读时,用表示fp.read(n),您会知道当EOF返回的n字符数少于字符时,您已击中EOF 。
Fred Foo 2012年

3
除非您出于某种原因要分块处理文件,否则逐行处理文件通常是更自然的做法,因为文件是迭代器,所以python提供了此功能-因此您可以执行for line in file: ...for循环来为您处理。
Gareth Latty

17
根据BufferedIOBase文档:“对于交互式原始流(tty /终端),短暂的结果并不意味着即将到来EOF。”
昆汀·普拉德

4
@larsmans刚刚使用了这个,谢谢!尽管我的是二进制流,但我在这里应该注意,if chunk == '':仅适用于文字串流,if chunk == b'':二进制流才需要,请注意额外的b。
矩阵异常

53

“其他”设计经常被忽略。请参阅:Python Docs“循环中的控制流”

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

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

29
实际上,这没有任何意义else:。不写它,只是bar()工作原理相同。else仅当您使用时才有所不同break
Artyer

可能有人读过这个并很在意:)我不知道您可以逐行迭代f(即使在二进制模式下也是如此!)。我不喜欢别的:它没有意义,只是增加了一行代码和更缩进的代码。就像最后在try / except中一样,它的目的和行为令人困惑。
Staplerfahrer

31

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

如果您知道这不是问题,则可以使用以下方法:

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

同意如果您调用read()并且您处于EOF,它将返回''
krystan荣誉

5
我更喜欢先fh.seek(0, 2); file_size = fh.tell(); fh.seek(0),然后fh.tell() == file_size再。以您的方式进行操作有好处吗?注意:我当然建议将大小缓存到​​一个变量中,而不是os.fstat在每个循环中都调用。
布鲁诺·布鲁诺斯基

2
请注意,如果在文本模式下打开文件,这将不起作用:f.tell()以字符os.fstat(f.fileno()).st_size为单位提供文件位置,以字节为单位提供文件长度。不过,@ BrunoBronosky的方法将起作用。
rmalouf '17

14

由于python在EOF上返回空字符串,而不是“ EOF”本身,因此您只需检查代码即可,写在这里

f1 = open("sample.txt")

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

5
文件中的空行破坏了该算法。
Leonardo Raele

4
@LeonardoRaele:空行将导致readlinereturn "\n"。仅当文件实际位于EOF时,它才返回空字符串。
randomdude999

13

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

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

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


这如何告诉您您是否在EOF?
GreenAsJade 2014年

@GreenAsJadef.read(1)将在EO​​F返回空字符串。
user545424 2014年

!而且……寻觅是必不可少的,而不仅仅是任何东西的一部分吗?它的作用是什么?
GreenAsJade 2014年

当您使用f.read(1)且文件不在at时EOF,您只读取了一个字节,因此f.seek(-1,1)告诉文件将文件后移一个字节。
user545424 2014年

1
@Chris,据我所知,任何非空字符串都将始终为True。您可以通过运行在解释器中进行检查bool('\0')
user545424'9

9

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

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


fp.tell()例如,如果它处于迭代状态,则不能使用:OSError: telling position disabled by next() call
Andry


6
f=open(file_name)
for line in f:
   print line

非常pythonic,没有其他测试
fcm

使用f = open(...)而不是时with open(...) as f,您还应该确保f.close()在完成操作后致电,否则可能会有意想不到的副作用
Lovethenakedgun

6

我真的不明白为什么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

这种方法很简单,您不需要更改大多数代码。


4

如果以非阻塞模式打开文件,则返回的字节数少于预期数量并不意味着它处于eof位置,我想说@NPE的答案是最可靠的方法:

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


2

如果Python读取函数达到EOF,则将返回空字符串


2
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()来确定文件末尾的位置。找到位置后,返回到文件开头


您能通过编辑帖子来说明您的解决方案在做什么吗?仅发布代码通常是不够的。
Noel Widmer

2

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

以下是两个实现。

使用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)

玩这个代码



1

您可以tell()EOF调用方法后使用方法readlines() ,如下所示:

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

您能格式化这篇文章吗?它似乎有一个很难阅读的代码片段,因为它全部格式化为一行。
亨利·克鲁彻

1

获取文件的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()


0

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

使用try-catchEOFError作为例外:

try:
    input_lines = ''
    for line in sys.stdin.readlines():
        input_lines += line             
except EOFError as e:
    print e

0

分批读取文件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

此代码适用于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()

-1

我使用此功能:

# 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

我想您打算在最后一行中测试是否相等。
蓝精灵爸爸

-5

您可以使用下面的代码片段逐行读取,直到文件结尾:

line = obj.readline()
while(line != ''):
    # Do Something
    line = obj.readline()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.