【问题标题】:Using python, how to read a file starting at the seventh line ?使用python,如何读取从第七行开始的文件?
【发布时间】:2011-02-01 15:22:05
【问题描述】:

我的文本文件结构为:

date
downland

user 

date data1 date2
201102 foo bar 200 50
201101 foo bar 300 35

因此不需要前六行文件。文件名:dnw.txt

f = open('dwn.txt', 'rb')

如何从第 7 行开始将该文件“拆分”为 EOF?

【问题讨论】:

  • 一般来说,您将如何逐行读取文件?你的教程解释了吗?
  • 我的教程。没有.... 我最常用的方法是 for line in ???.split("\r\n"): 这是你的问题吗?
  • 为什么要以二进制模式读取文本文件?

标签: python file-io


【解决方案1】:
with open('dwn.txt') as f:
    for i in xrange(6):
        f, next()
    for line in f:
        process(line)

更新:在 python 3.x 中使用 next(f)

【讨论】:

  • 两位(到目前为止)匿名投票者有没有机会分享他们的智慧?
  • 老实说,这是最地道的解决方案,代码直接告诉你它的作用。
  • @user428862: process(line) 是“在此处插入您自己的代码以使用line 做任何您想做的事情”的伪代码。 “ur”码是什么码?
  • 再次感谢代码示例,您的代码更快。由于 dwn.txt 来自互联网,将用于多线程脚本。
  • 这不适用于Python 3.x。得到AttributeError: '_io.TextIOWrapper' object has no attribute 'next'
【解决方案2】:

Itertools 回答!

from itertools import islice

with open('foo') as f:
    for line in islice(f, 6, None):
        print line

【讨论】:

  • 这比它需要的复杂。
  • 如果你想使用 itertools 那么islice 会是一个更好的选择。
  • @Jochen islice,谢谢。我一直在寻找一种叫做“drop”的东西,但什么也找不到。
  • 这怎么是大锤?它需要一行设置。
  • @recursive:它还需要导入,并且对于某些代码读者可能还需要查看手册。
【解决方案3】:

Python 3:

with open("file.txt","r") as f:
    for i in range(6):
        f.readline()
    for line in f:
        # process lines 7-end

【讨论】:

  • 基本上我认为您将“光标”向前推了 6 次:“list(range(6)) 或 [0, 1, 2, 3, 4, 5]”中的每一个。因此,第 7 行是下一个。然后开始处理。如果我理解正确就很聪明。
【解决方案4】:
with open('test.txt', 'r') as fo:
   for i in xrange(6):
       fo.next()
   for line in fo:
       print "%s" % line.strip()

【讨论】:

    【解决方案5】:

    事实上,要准确地回答问题,因为它是书面的

    How do I "split" this file starting at line 7 to EOF?
    

    你可以的

    如果文件不大:

    with open('dwn.txt','rb+') as f:
        for i in xrange(6):
            print f.readline()
        content = f.read()
        f.seek(0,0)
        f.write(content)
        f.truncate()
    

    如果文件很大

    with open('dwn.txt','rb+') as ahead, open('dwn.txt','rb+') as back:
        for i in xrange(6):
            print ahead.readline()
    
        x = 100000
        chunk = ahead.read(x)
        while chunk:
            print repr(chunk)
            back.write(chunk)
            chunk = ahead.read(x)
        back.truncate()
    

    truncate() 函数对于放置您要求的 EOF 至关重要。如果不执行 truncate() ,文件的尾部,对应 6 行的偏移量将保留。

    .

    文件必须以二进制模式打开以防止出现任何问题。

    当 Python 读取 '\r\n' 时,会将它们转换为 '\n' (即通用换行支持,默认启用),即假设链 chunk 中只有 '\n',即使文件中有 '\r\n'

    如果文件来自 Macintosh origin ,则在处理前仅包含 CR = '\r' 换行符,但它们将更改为 '\n' 或 '\r\n'(根据平台)在非 Macintosh 机器上重写期间。

    如果是来自 Linux 的文件,它只包含 LF = '\n' 换行符,在 Windows 操作系统上,换行符将更改为 '\r\n' (我不知道在 Macintosh 上处理的 Linux 文件)。 原因是操作系统 Windows 写入 '\r\n' 无论它被命令写入,'\n''\r' > 或 '\r\n'。因此,重写的字符将多于读取的字符,然后文件指针 aheadback 之间的偏移量将减小并导致重写混乱。

    在 HTML 源代码中,也有各种换行符。

    这就是为什么在处理文件时最好以二进制模式打开文件。

    【讨论】:

      【解决方案6】:

      替代版本

      如果您知道分隔(标题部分与感兴趣部分)换行符的字符位置pos,则可以直接使用命令read(),例如一个\n,在您要中断输入文本的文本中:

      with open('input.txt', 'r') as txt_in:
          txt_in.seek(pos)
          second_half = txt_in.read()
      

      如果你对两半都感兴趣,还可以研究以下方法:

      with open('input.txt', 'r') as txt_in:
          all_contents = txt_in.read()
      first_half = all_contents[:pos]
      second_half = all_contents[pos:]
      

      【讨论】:

        【解决方案7】:

        您可以将整个文件读入一个数组/列表,然后从与您希望开始读取的行对应的索引处开始。

        f = open('dwn.txt', 'rb')
        fileAsList = f.readlines()
        fileAsList[0] #first line
        fileAsList[1] #second line
        

        【讨论】:

          【解决方案8】:
          #!/usr/bin/python
          
          with open('dnw.txt', 'r') as f:
              lines_7_through_end = f.readlines()[6:]
          
          print "Lines 7+:"
          i = 7;
          for line in lines_7_through_end:
              print "    Line %s: %s" % (i, line)
              i+=1
          

          打印:

          第 7 行以上:

            Line 7: 201102 foo bar 200 50
          
            Line 8: 201101 foo bar 300 35
          

          编辑:

          要在没有前六行的情况下重建dwn.txt,请在上述代码之后执行此操作:

          with open('dnw.txt', 'w') as f:
              for line in lines_7_through_end:
                  f.write(line)
          

          【讨论】:

          • 使用 with: open('dnw.txt', 'r') as f: lines = f.readlines()[6:] for line in lines: print " %s" % (line )
          • 这就是 SO 最好的一切都被摧毁的方式。
          • @SG 它的额外信息会使数据库变得混乱。
          • 从 Python 2.6 开始,可能比使用专用索引更优雅:for (i, line) in enumerate(lines_7_through_end, 7):... 这避免了增加 i
          • 我认为没有必要打印Line 7, Line 8
          【解决方案9】:

          我创建了一个脚本,用于每天多次剪切 Apache access.log 文件。 这不是问题的原始主题,但我认为它可能很有用,如果您在读取 ​​6 行第一行之后存储了文件光标位置。

          所以我需要在上次执行期间解析的最后一行设置位置光标。 为此,我使用了file.seek()file.seek() 方法,它们允许将光标存储在文件中。

          我的代码:

          ENCODING = "utf8"
          CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
          
          # This file is used to store the last cursor position
          cursor_position = os.path.join(CURRENT_FILE_DIR, "access_cursor_position.log")
          
          # Log file with new lines
          log_file_to_cut = os.path.join(CURRENT_FILE_DIR, "access.log")
          cut_file = os.path.join(CURRENT_FILE_DIR, "cut_access", "cut.log")
          
          # Set in from_line 
          from_position = 0
          try:
              with open(cursor_position, "r", encoding=ENCODING) as f:
                  from_position = int(f.read())
          except Exception as e:
              pass
          
          # We read log_file_to_cut to put new lines in cut_file
          with open(log_file_to_cut, "r", encoding=ENCODING) as f:
              with open(cut_file, "w", encoding=ENCODING) as fw:
                  # We set cursor to the last position used (during last run of script)
                  f.seek(from_position)
                  for line in f:
                      fw.write("%s" % (line))
          
              # We save the last position of cursor for next usage
              with open(cursor_position, "w", encoding=ENCODING) as fw:
                  fw.write(str(f.tell()))
          

          【讨论】:

            【解决方案10】:

            只需执行六次 f.readline() 即可。忽略返回值。

            【讨论】:

            • 你试过自己做吗?这个答案怎么可能有两个赞成票?是否有一些邪恶的 perl 黑客支持或其他什么?
            • 我的意思是 f.readline()。 .next() 不过更好。你们赢了。我输了。
            • 虽然如果你 .next() 然后尝试 .readline() 得到一个 ValueError 用于混合迭代和读取方法。
            • 您出于正当理由对“readlines()”解决方案投了反对票,但为什么要对 readline() [times 6] 解决方案投反对票?当然,这不会读取整个文件。还要注意我对 .next() 和 .readline() 的问题。
            • @Spacedman:因为 readline() 是老帽子,而且因为你提到的问题
            【解决方案11】:

            readlines() 的解决方案在我看来并不令人满意,因为 readlines() 会读取整个文件。用户将不得不再次阅读这些行(在文件中或在生成的列表中)以处理他想要的内容,而无需第一次阅读有趣的行就可以完成。此外,如果文件很大,内存会被文件内容占用,而for line in file 指令会更轻。

            重复 readline() 可以这样完成

            nb = 6
            exec( nb * 'f.readline()\n')
            

            代码很短,nb 可以通过编程方式调整

            【讨论】:

            • 你是认真的吗? exec。平心而论!
            • +1 表示不将整个文件读入内存,-100 表示使用exec
            • 对 exec() 有什么好处?它仍然在 Python 3 中;如果它和 xreadlines() 一样糟糕,那么它也会被弃用。我从不使用 exec(),但在我看来,在这种情况下,它可以缩短代码,而不是用 readline() 写 6 行
            • « 在我看来,使用 readlines() 的解决方案并不令人满意,因为 readlines() 会读取整个文件。 » 嗯,可以讨论。这取决于文件和目标。如果一个文件很大并且只有几行是有趣的,那么在重新阅读之前阅读整个文件并不是一个好主意。但是,如果不是很大并且列表中的所有行都简化了代码或其他任何内容,那么它是可以接受的。这取决于。我不再同意自己了。
            猜你喜欢
            • 1970-01-01
            • 2014-09-18
            • 1970-01-01
            • 2017-03-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多