2016-07-18 2 views
3

ファイルに行を表示したい場合は、削除する行を決定してから、すべての行をファイルに書き戻します(ユーザーが削除したい行を除く)。ファイル内の行を削除する

これはこれまで私が試したことですが、私はちょっと固まっています。

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; 
あなたは名前でそれを行う場合
+0

ユーザー名や行番号を削除しようとしていますか? – danidee

+0

5行目と10行目を削除したい場合は5行目を削除する5行目を変更するか、削除したい行なしにファイルを書き直す必要がありますか? – depperm

+0

@danidee username –

答えて

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

編集:私はあなたが名前で削除したいと思ったことを見ました、行番号ではなく、@ danideeのメソッドに似ています。

+1

EOLは\ n、\ rまたは\ r \ nになります。ファイルを作成したOSの規則および/またはエディタ。したがって、line.rstrip( "\ n")。rstrip( "\ r")を使うか、ファイル全体をRAMにロードしてからcontent.splitlines()を読み込み、EOLについて心配する必要はありません。また、readline()/ readlines()の結果を取り除くと、ファイルオブジェクトには、有効なNLセパレータを含むべきnewlinesという属性が含まれます。 – Dalen

+0

@Dalenそれは良い点です。唯一の問題は、どの改行を追加するかを知ることです(新しいファイルが行単位で記述されていれば気にならないでしょう)。提案していただきありがとうございます! – Alec

+1

おそらく、最初のreadline()からEOLを取得し、全体のファイルを通してそれを私たちの人にしてください。その後、必要に応じて残りの部分を処理します。ちょうどアイデア。 – Dalen

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

私が書いた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' 
+1

読み込みたい巨大なtxtファイルやファイルに書き込む項目がたくさんある場合は、 'readlines'や' writelines'を使用しないでください。時間 – danidee

+0

ニースのアプローチ先生..少し答えを修正し、下に.. ..投稿! –

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

他のすべての答えが有効ですファイルを保存し、内容を変更してファイルを保存し直します。

ファイルの内容をストレージメモリに直接変更する可能性があることを指摘したいだけです。そうすることは常に賢明ではないが、問題には欠点があるが、それは将来のある用途では有用かもしれないからである。

コンテンツを既存のファイルに変更(削除または挿入)するには、mmapモジュールを使用します。

RAMやストレージのメモリ(ファイル)の一部をマップし、文字列のようにアクセスして編集することができます。たぶんそれは言いたいことでしょう。

ファイルを開くには、ファイルを開き、その内容を読み込んでfind()などを実行して、削除する行のインデックスとその長さを探します。

ファイルをメモリマップし、削除したい行の次の部分を上に移動するだけで不要な行を「カバー」するだけです。あなたはスライスを使ってそれを行います。次に、コンテンツを移動した後、残りのバイトを切り捨てるようにメモリマップのサイズを変更します。したがって、ファイルのサイズを正しいサイズに変更してから、ファイルを閉じないmmapを閉じることができます。

このようにしてファイルに行を挿入することができます。最初にファイルのサイズを変更し、最後にコンテンツをシフトして、行を表示するスペースを作り、それを書き込んでください。

少し複雑で作業は多いようですが、そうではありません本当に。これは、行を削除するたびにファイル全体を書き込む手間を省きます。

私はそれがどれほど速いかを確認しておらず、毎回上書きするよりも速いです。しかし、これは私が言及する価値があると感じた1つの解決策です。ここで

は、いくつかの迅速組み立てコードです:



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

+0

意味があります。コード例を見たいと思っています。共有してくれてありがとう! –

+0

コード例を追加しました。ちょっと大きめです。慎重に使用してください。 – Dalen

関連する問題