【问题标题】:How to find out whether a file is at its `eof`?如何找出文件是否在其`eof`?
【发布时间】:2012-04-13 11:52:08
【问题描述】:
fp = open("a.txt")
#do many things with fp

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

除了上面的方法,还有什么方法可以判断fp是否已经在eof了?

【问题讨论】:

  • 打开文件的with statement 值得一看 - 它很好地为您处理关闭和异常,并且读起来很好。

标签: python file eof


【解决方案1】:

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)

【讨论】:

  • 是的,你是对的。所以没有有效的方法来检查是否达到eof
  • @Alcott:普通文件有aix的方法。当分块阅读时,比如使用fp.read(n),当返回少于n 个字符时,你会知道你已经点击了EOF。
  • 除非你有理由分块处理文件,否则通常更自然地逐行处理它,python 提供的文件是迭代器 - 所以你可以只做for line in file: ... 并让for循环为你处理。
  • 根据BufferedIOBase doc:“对于交互式原始流(tty/终端),简短的结果并不意味着EOF迫在眉睫。”
  • @larsmans 刚刚使用了这个,谢谢!虽然我的是用于二进制流,但我应该在这里注意if chunk == '': 仅适用于文字字符串流,if chunk == b'': 需要用于二进制流,请注意额外的 b。
【解决方案2】:

“for-else”设计经常被忽视。见:Python Docs "Control Flow in Loop":

示例

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

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

【讨论】:

  • 这个else: 毫无意义。不写它,只是让bar() 工作相同。 else 只有在您使用 break 时才会有所作为。
  • 有人可能会阅读并关心 :) 我不知道您可以逐行迭代 f(即使在二进制模式下!)。我不是 else 的粉丝:没有意义,它只是添加了一行和更多缩进的代码。它的目的和行为就像 try/except 中的 finally 一样令人困惑。
【解决方案3】:

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

如果你知道这不是问题,你可以使用类似的东西:

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

【讨论】:

  • 同意,如果你调用 read() 并且你在 EOF 它将返回 ''
  • 我更喜欢先fh.seek(0, 2); file_size = fh.tell(); fh.seek(0),然后再选择fh.tell() == file_size。以你的方式做有优势吗?注意:我当然建议将大小缓存到​​一个变量中,而不是在每个循环中调用 os.fstat
  • 请注意,如果文件以文本模式打开,这将不起作用:f.tell() 以字符为单位提供文件位置,os.fstat(f.fileno()).st_size 以字节为单位提供文件长度。不过,@BrunoBronosky 的方法会奏效。
【解决方案4】:

由于 python 在 EOF 上返回空字符串,而不是“EOF”本身,你可以检查它的代码,写在这里

f1 = open("sample.txt")

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

【讨论】:

  • 文件中的空行破坏了这个算法。
  • @LeonardoRaele:空行会导致readline 返回"\n"。如果文件实际上在 EOF,它只返回一个空字符串。
  • 为什么不if not line: break
【解决方案5】:

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

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

优点是有时你正在处理一个二进制流并且事先不知道你需要读取多少。

【讨论】:

  • 这如何告诉您您是否在 EOF?
  • @GreenAsJade, f.read(1) 将在 EOF 处返回空字符串。
  • 嗯!而且……寻求是必不可少的,而不仅仅是任何事情的一部分吗?它的作用是什么?
  • 当你使用f.read(1)并且文件不在EOF,那么你只读取一个字节,所以f.seek(-1,1)告诉文件向后移动一个字节。
  • @Chris,据我所知,任何非空字符串都将始终评估为 True。您可以通过运行bool('\0') 在解释器中检查这一点。
【解决方案6】:

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

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

【讨论】:

  • 不能使用fp.tell(),例如处于迭代状态:OSError: telling position disabled by next() call
【解决方案7】:

read 在遇到 EOF 时返回一个空字符串。文档是here

【讨论】:

    【解决方案8】:
    f=open(file_name)
    for line in f:
       print line
    

    【讨论】:

    • 非常pythonic,没有额外的测试
    • 当使用f = open(...)而不是with open(...) as f时,您还应该确保在完成后调用f.close(),否则可能会出现意外的副作用
    【解决方案9】:

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

    这个方法很简单,你不需要改变大部分代码。

    【讨论】:

      【解决方案10】:

      这是使用 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

      【讨论】:

        【解决方案11】:

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

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

        【讨论】:

          【解决方案12】:

          Python 读取函数在到达 EOF 时将返回一个空字符串

          【讨论】:

            【解决方案13】:
            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>
            

            您可以使用file methods seek()tell() 来确定文件的结尾。找到位置后,回到文件开头

            【讨论】:

            • 你能通过编辑你的帖子来解释你的解决方案在做什么吗?仅发布代码通常是不够的。
            【解决方案14】:

            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)
            

            Play with this code.

            【讨论】:

            • 为什么不在if s: f.seek( ... )# restore position
            【解决方案15】:

            您可以在到达EOF 后通过调用readlines() 使用tell() 方法 方法,像这样:

            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
            

            【讨论】:

            • 你能格式化这篇文章吗——它似乎有一个难以阅读的代码 sn-p,因为它的格式都在一行上。
            【解决方案16】:

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

            【讨论】:

              【解决方案17】:

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

              使用 EOFError 的 try-catch 作为例外:

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

              【讨论】:

                【解决方案18】:

                我使用这个功能:

                # 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
                

                【讨论】:

                • 我想你的意思是在最后一行测试相等性。
                【解决方案19】:

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

                【讨论】:

                  【解决方案20】:

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

                  【讨论】:

                    【解决方案21】:

                    你可以试试这个代码:

                    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
                    

                    【讨论】:

                    • 解释为什么要试用此代码。
                    【解决方案22】:

                    您可以使用下面的代码 sn-p 逐行读取,直到文件末尾:

                    line = obj.readline()
                    while(line != ''):
                        # Do Something
                        line = obj.readline()
                    

                    【讨论】:

                      猜你喜欢
                      • 2010-09-07
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-01-06
                      • 2017-08-17
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多