Python 删除文件中的行

Python 删除文件中的行,python,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

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

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

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()

minigolf.txt包含:

Sara;37;32;47;
Johan;44;29;34;
Kalle;33;34;34;
Oskar;23;47;45;
如果你用名字;试试看:

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()

这将解决您的问题,并为您提供一种更稳健的方式来处理用户输入:

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()

编辑:我看到您想按名称而不是行号删除,所以将其更改为类似于@danidee的方法。

为了清晰起见,对danidee的答案进行了轻微修改

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'
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...

所有其他答案都是有效的,因此您可能对如何加载文件、更改内容然后将文件保存回去有了很好的了解

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

要将内容更改(删除或插入)到现有文件中,可以使用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()


您是否尝试使用用户名或行号删除?如果用户想要删除第5行和第10行,删除第5行是否会改变第10行是什么,或者您是否必须基本上重写文件,而不包含他们想要删除的行?@depperm基本上重写文件,而不包含他们想要删除的行请注意,您不应该使用
readlines
writelines
如果你有一个巨大的txt文件要读,或者有很多项目要写入文件,你最好循环阅读它们,然后一次一个地写/读这些项目。。稍微修改了答案并贴在下面。。!EOL可以是\n、\r或\r\n,具体取决于生成该文件的操作系统的约定和/或编辑器。所以最好使用line.rstrip(“\n”).rstrip(“\r”),或者将整个文件加载到RAM中,然后再加载content.splitlines(),不用担心EOL。另外,如果剥离readline()/readlines(),则文件对象包含一个名为newlines的属性,该属性应包含OS有效的NL分隔符。@Dalen这是一个很好的观点,唯一的问题是知道要重新添加哪些换行符(我想,如果新文件是逐行写入的,这不会引起关注)。谢谢你的建议!也许从first readline()获取EOL,并将其作为我们的人完成整个文件。然后以任何适合需要的方式处理其余部分。只是个想法,有道理。。渴望看到一个代码示例。。谢谢分享!我添加了代码示例。有点笨重。小心使用。
>> 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...


# 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()