删除文件中的行

时间:2016-07-18 13:11:45

标签: python

我想在文件中显示行,让用户决定应删除哪一行,然后将所有行写回文件,但用户想要删除的行除外。

这是我到目前为止所尝试的,但我有点卡住了。

def delete_result():
    text_file = open('minigolf.txt', 'r')
    zork = 0
    for line in text_file:
        zork = zork + 1
        print zork, line

    delete_player = raw_input ("Who's result do you want to delete?")

    text_file.close()

def delete_result():
    text_file = open('minigolf.txt', 'r')
    for line in text_file:
        if ';' in line:
            line2 = line.split(";")
        print line2
    print "***"
    delete = raw_input ("Who's result do you want to delete? ")

    text_file.close()

minigolf.txt包含:

Sara;37;32;47;
Johan;44;29;34;
Kalle;33;34;34;
Oskar;23;47;45;

5 个答案:

答案 0 :(得分:2)

所有其他答案都是有效的,因此您可能通过加载文件,更改内容然后再保存文件来了解如何操作。

我只想指出,有可能直接在存储内存中更改文件的内容。这样做并不总是明智的,事情有它的缺点,但是因为它可能对将来的一些用途有用。

要将内容更改(删除或插入)到现有文件,您可以使用mmap模块。

它允许您映射RAM或存储内存(文件)的一部分,并像访问字符串一样访问和编辑它。或许可以说一个清单。

因此,要删除所需的行,请打开文件,加载其内容并执行find()或其他内容,以查找要删除的行的索引及其长度。

然后你记忆地映射文件,然后简单地移动你想要向上删除的行的其余内容,因此"覆盖"不需要的线。你使用切片来做到这一点。然后在移动内容后调整内存映射的大小以切断剩余的字节。因此,您将文件大小调整为正确大小,然后您可以关闭不会关闭文件的mmap。

您可以这种方式将一行插入文件中。您首先调整文件大小,将内容移到最后,以便在您希望显示行的位置创建一个空格,并将其写入。

这听起来有点复杂,而且工作量很大,但实际上并非如此。每次删除行时都可以省去编写整个文件的麻烦。

我没有检查它的速度有多快,而且每次覆盖速度都快。但这是我觉得值得一提的一个解决方案。

以下是一些快速汇编的代码:



# This needs checks and rechecks
# Also, its efficiency is questionable. Some optimization can be done with find() and rfind()
# But we can choose to believe in the module and just do it.
# The nice thing is that we can use find() to point the user, not searching for the line number like mad.

from mmap import mmap

def removeline (fname, nl):
    f = open(fname, "rb+")
    m = mmap(f.fileno(), 0)
    size = m.size()
    ixl = 0 # Index of line to delete
    nle = 0 # Count new lines found
    # Find the line:
    while nle!=nl:
        # Suppose we know our EOL will always be \n
        i = m.find("\n", ixl)
        if i==-1: break
        ixl = i+1
        nle += 1
    if ixl>=size: f.close(); return # nl is greater than number of lines in the f
    ixle = m.find("\n", ixl) # Index of end of that line
    ixle = (ixle+1, None)[ixle==-1] #Either include the EOL in deletion or delete to the EOF
    # Line length:
    if ixle!=None: ll = ixle-ixl
    else:
        # Remove from ixl to the end of file.
        # I.e. just shrink the file.
        ns = size-(size-ixl)
        if ns==0:
            # Delete all
            m.close()
            f.close()
            f = open(fname, "wb")
            f.close()
            return
        m.resize(ns) # Cut off the rubbish
        m.close(); f.close()
        return
    # Shift the rest over the offending line:
    try: m[ixl:size-ll] = m[ixle:size]
    except:
        m.close()
        f.close()
        raise
    ns = size-ll
    if ns==0:
        # Delete all - mmap doesn't like to resize to 0 bytes., hm, perhaps f.truncate()
        m.close()
        f.close()
        f = open(fname, "wb")
        f.close()
        return
    m.resize(ns) # Cut off the rubbish
    m.close()
    f.close()

答案 1 :(得分:1)

line_number = 5 #for example
file = open("foo.txt")
cont = file.read()
cont = cont.splitlines()

cont.pop(line_number-1)
file.close()
file = open("foo.txt", "w")
cont= "\n".join(cont)
file.write(cont)
file.close()

如果你用名字做;试试看:

file = open("foo.txt")
cont = file.read()
cont = cont.splitlines()

line_number = 0 
name = "Johan"
for i in cont:
    if i.startswith(name):
        line_number = cont.index(i)


cont.pop(line_number)
file.close()
file = open("foo.txt", "w")
cont= "\n".join(cont)
file.write(cont)
file.close()

答案 2 :(得分:1)

def delete_result():
    with open('minigolf.txt', 'r') as f:
        results = f.readlines()
        print(results)

    user = raw_input('which user do you want to delete')

    for res in results:
        if user.lower() in res:  # assumption that sara == Sara
            results.remove(res)

            with open('minigolf.txt', 'w') as f:
                f.writelines(results)
                return 'user was found and removed'

    return 'user was not found'

答案 3 :(得分:1)

为了清晰起见,对danidee的回答稍作修改

def delete_result():
    with open('minigolf.txt', 'r') as f:
        results = f.readlines()
        print "\n".join(results)

    delete_player = raw_input ("Who's result do you want to delete?")
    deleted = False

    for res in results:
        if delete_player.lower() in res.lower():
            results.remove(res)

            with open('minigolf.txt', 'w') as f:
                f.writelines(results)
                print "User was found and removed"        
                deleted = True
    # for

    if not deleted:
        print "User not found..."
# def

结果:

>> python delete_user.py
Sara;37;32;47;

Johan;44;29;34;

Kalle;33;34;34;

Oskar;23;47;45;
Who's result do you want to delete?sara
User was found and removed

>> cat minigolf.txt
Johan;44;29;34;
Kalle;33;34;34;
Oskar;23;47;45;
>> python delete_user.py
Johan;44;29;34;

Kalle;33;34;34;

Oskar;23;47;45;
Who's result do you want to delete?nonuser
User not found...

答案 4 :(得分:0)

这将解决您的问题并为您提供更强大的处理用户输入的方式:

def delete_result():
    with open('minigolf.txt', 'r') as f:
        text_file = f.readlines()

    # find newline char and strip from endings
    if '\r' in text_file[0]:
        if '\n' in text_file[0]:
            newline = '\r\n'
        else:
            newline = '\r'
    else:
        newline = '\n'
    text_file = [t[:-len(newline)]
                    if t[-len(newline):] == newline
                        else t for t in text_file]

    users = set()
    for line_number, line in enumerate(text_file):
        print line_number + 1, line
        users.add(line[:line.index(';')].lower())

    # get result from user with exception handling
    result = None
    while not result:
        delete_player = raw_input('Which user do you want to delete? ')
        try:
            result = str(delete_player).lower()
            assert result in users
        except ValueError:
            print('Sorry, I couldn\'t parse that user.')
        except AssertionError:
            print('Sorry, I couldn\'t find that user.')
            result = None

    # write new file
    new_file = [t + newline for t in text_file
                             if t[:t.index(';')].lower() != result]
    with open('minigolf.txt', 'w') as f:
        f.writelines(new_file)

if __name__ == '__main__':
    delete_result()
编辑:我看到你想要删除 name ,而不是行号,所以把它改成类似@ danidee的方法。