代码之家  ›  专栏  ›  技术社区  ›  torger

用python删除文件中的最后一行

  •  29
  • torger  · 技术社区  · 16 年前

    如何用python删除文件的最后一行?

    输入文件示例:

    hello
    world
    foo
    bar
    

    输出文件示例:

    hello
    world
    foo
    

    我创建了以下代码来查找文件中的行数-但我不知道如何删除特定的行数。我刚接触过python,所以如果有更简单的方法,请告诉我。

        try:
            file = open("file")
        except IOError:
            print "Failed to read file."
        countLines = len(file.readlines())
    

    编辑:

    我用各种各样的答案来解决这个问题:主要是草莓味的和我在网上看到的东西(对不起,我找不到链接)。

    #!/usr/bin/env python
    
    import os, sys
    
    readFile = open("file")
    
    lines = readFile.readlines()
    
    readFile.close()
    w = open("file",'w')
    
    w.writelines([item for item in lines[:-1]])
    
    w.close()
    
    10 回复  |  直到 9 年前
        1
  •  9
  •   Martin    16 年前

    您可以使用上述代码,然后:

    lines = file.readlines()
    lines = lines[:-1]
    

    这将为您提供一个包含除最后一行以外的所有行的行数组。

        2
  •  60
  •   Chris Lieb    11 年前

    因为我经常处理许多千兆字节的文件,所以在回答中提到的循环不适用于我。我使用的解决方案:

    file = open(sys.argv[1], "r+", encoding = "utf-8")
    
    #Move the pointer (similar to a cursor in a text editor) to the end of the file. 
    file.seek(0, os.SEEK_END)
    
    #This code means the following code skips the very last character in the file - 
    #i.e. in the case the last line is null we delete the last line 
    #and the penultimate one
    pos = file.tell() - 1
    
    #Read each character in the file one at a time from the penultimate 
    #character going backwards, searching for a newline character
    #If we find a new line, exit the search
    while pos > 0 and file.read(1) != "\n":
        pos -= 1
        file.seek(pos, os.SEEK_SET)
    
    #So long as we're not at the start of the file, delete all the characters ahead of this position
    if pos > 0:
        file.seek(pos, os.SEEK_SET)
        file.truncate()
    
    file.close()
    
        3
  •  6
  •   Peter    16 年前

    这不使用python,但如果这是您唯一想要的任务,那么python是该作业的错误工具。您可以使用标准*nix实用程序 head 并运行

    head -n-1 filename > newfile
    

    它将把文件名的最后一行复制到newfile。

        4
  •  4
  •   Dan Head    16 年前

    假设您必须在python中这样做,并且您有一个足够大的文件,而列表切片还不够,那么您可以在一次文件传递中这样做:

    last_line = None
    for line in file:
        if last_line:
            print last_line # or write to a file, call a function, etc.
        last_line = line
    

    不是世界上最优雅的代码,但它可以完成任务。

    基本上,它通过最后一个行变量缓冲文件中的每一行,每个迭代输出上一个迭代行。

        5
  •  3
  •   Laurence Gonsalves    16 年前

    在系统上 file.truncate() 你可以这样做:

    file = open('file.txt', 'rb')
    pos = next = 0
    for line in file:
      pos = next # position of beginning of this line
      next += len(line) # compute position of beginning of next line
    file = open('file.txt', 'ab')
    file.truncate(pos)
    

    根据我的测试,当按行读取时,file.tell()不起作用,可能是因为缓冲会混淆它。这就是为什么要把这些线的长度加起来计算位置。注意,这只适用于行分隔符以'\n'结尾的系统。

        6
  •  1
  •   Moj    9 年前

    以下是我针对Linux用户的解决方案:

    import os 
    file_path = 'test.txt'
    os.system('sed -i "$ d" {0}'.format(file_path))
    

    不需要在python中读取和迭代文件。

        7
  •  1
  •   Mohammad M. Shahbazi    9 年前

    在之前的文章中,我提出了以下观点:

    with open('file_name', 'r+') as f:
      f.seek(0, os.SEEK_END) 
      while f.tell() and f.read(1) != '\n':
        f.seek(-2, os.SEEK_CUR)
      f.truncate()
    
        8
  •  0
  •   Isaac    16 年前

    虽然我还没有测试过(请不要恨这个),但我相信有一个更快的方法。它更像是一个C解决方案,但在Python中是完全可能的。也不是蟒蛇。我想说,这是一种理论。

    首先,您需要知道文件的编码。将变量设置为该编码中字符使用的字节数(1字节为ASCII)。 字符大小 (为什么不呢?)可能是一个1字节的ASCII文件。

    然后抓取文件的大小,设置 文件化 对它。

    假设您在 文件添加 .

    添加 文件化 到 文件添加 .

    移动backwords(增量为-1***charsize**),测试每个charsize字节的\n(或系统使用的任何换行符)。当您到达第一行\n时,您现在拥有文件第一行的起始位置。将\n替换为\x1a(26,用于eof的ASCII,或是您的系统/使用编码的任何内容)。

    根据需要清理(更改文件大小,触摸文件)。

    如果这能像我猜想的那样工作,你就可以节省很多时间,因为你不需要从一开始就通读整个文件,而是从最后读。

        9
  •  0
  •   ghostdog74    16 年前

    这是另一种方法,不用把整个文件拖进内存

    p=""
    f=open("file")
    for line in f:
        line=line.strip()
        print p
        p=line
    f.close()
    
        10
  •  0
  •   Ned Deily    16 年前

    这里有一个更通用的内存效率解决方案,允许跳过最后的n行(如 head 命令):

    import collections, fileinput
    def head(filename, lines_to_delete=1):
        queue = collections.deque()
        lines_to_delete = max(0, lines_to_delete) 
        for line in fileinput.input(filename, inplace=True, backup='.bak'):
            queue.append(line)
            if lines_to_delete == 0:
                print queue.popleft(),
            else:
                lines_to_delete -= 1
        queue.clear()