2017-02-24 66 views
2

如果已經提出類似的問題,我們抱歉 - 我的確搜索了一下,我可能錯過了一些東西,但在我看來,至少對於其他問題的答案並不是我想要的同一件事做。在原地修改文本文件的最佳方法是什麼?

我有一個文本文件,(姑且稱之爲「Potatoes.txt」)包含以下信息:

Town 1,300, 
Town 2,205, 
Town 3,600, 
Town 4,910, 
Town 5,360, 

我想要做的就是減少對某些城市的數量,並修改文本文件因此。 我做了一些研究,它似乎無法修改的文本文件,我需要的文本文件具有相同的名稱,只是在其內部都有不同的價值觀,所以目前我在做這個:

f = open("ModifiedPotatoes.txt","w") 
f.close() 

with open("Potatoes.txt","r") as file: 
    for line in file: 
     info = line.split(",") 
     if "Town 2" or "Town 4" in line: 
      info[1] -= 20 
     with open("ModifiedPotatoes.txt","a"): 
      infoStr = "\n" + ",".join(str(x) for x in info) 
      file.write(infoStr) 

f = open("Potatoes.txt","w") 
f.close() 

with open("ModifedPotatoes.txt","r") as file: 
    for line in file: 
     with open("Potatoes.txt","a") as potatoesFile: 
      potatoesFile.write(line) 

所以基本上我只是覆蓋舊文件到一個空白的,然後從修改/臨時文件複製值。有沒有更好的方法來做到這一點我失蹤了?

感謝您的幫助。

+1

[Python:修改某些字符後的文本文件]可能的重複(http://stackoverflow.com/questions/19134163/python-modifying-text-file-after-certain-character)和[修改現有文本中的參數文件與Python](http://stackoverflow.com/q/17067573/62576)和許多其他(在這裏搜索* python修改文本文件*)。 –

+0

文件中的城鎮的順序是否重要?該文件有多大(我們可以將它全部裝入內存)? –

+0

不要忘記在'open'(「ModifedPotatoes.txt」,「r」)中使用'w'而不是'r'作爲文件:' – Aidenhjj

回答

0

嘗試:

mod_lines = [] 

with open("Potatoes.txt", "r") as f: 
    for line in f: 
     info = line.split(",") 
     if info[0] in ("Town 2", "Town 4"): 
      info[1] = int(info[1]) - 20 
     mod_lines.append(info) 

with open("Potatoes.txt", "w") as f: 
    for m in mod_lines: 
     f.write(",".join([str(x) for x in m])) 

這當然不是最好的方式,但它肯定更好的作品。

1

我做了一些研究,看來你不能修改文本文件

有,讓你的修改文本,你遍歷它的效果相同的模塊。嘗試使用fileinput模塊,將置於選項設置爲True

這裏是一個小Python3.6代碼,讓你開始:

from fileinput import FileInput 

with FileInput(files=['Potatoes.txt'], inplace=True) as f: 
    for line in f: 
     line = line.rstrip() 
     info = line.split(",") 
     if "Town 2" in line or "Town 4" in line: 
      info[1] = int(info[1]) - 20 
      line = ",".join(str(x) for x in info)) 
     print(line) 
0

可以使用csv模塊做文件/字符串處理。

只需讀取所有值並逐行循環,根據需要進行調整。然後使用csv.writer對象將它們寫回新文件。

import csv 
import shutil 
import os 

with open('potatoes.txt') as f, open('newpotatoes.txt', 'w') as fout: 
    rdr = csv.reader(f) 
    wrt = csv.writer(fout) 

    for line in rdr: 
     if line[0] in ('Town 2', 'Town 4'): 
      line[1] = str(int(line[1]) - 20) 
     wrt.writerow(line) 

shutil.copyfile('newpotatoes.txt', 'potatoes.txt') 
os.remove('newpotatoes.txt') 

line[1] = str(int(line[1]) - 20) 

是可能有點混亂。它的出現是因爲csv的值都是字符串。所以這是一個簡單的方法將它轉換爲整數,減去20並轉換回字符串。

看看你的代碼,初學者經常犯的錯誤。

if "Town 2" or "Town 4" in line: 

你必須認識到,這是兩個單獨的語句的組合,而不是你所期望的。第一個陳述只是Town 2,它總是會評估爲True。第二個語句是"Town 4" in line",如果字符串「Town 4」包含在line字符串中的任何位置,它將返回True。

你的意圖是毫無疑問地測試任一字符串是否在line。要做到這一點,你需要顯式測試兩個字符串。

if "Town 2" in line or "Town 4" in line: 

將按預期工作。儘管如此,你可以進一步採取措施,並在該聲明中刪減一些不雅之處。

你知道該字符串應該總是發生在字符串的第一個元素,後split這是你的代碼info[0](或line[0]在我爲我讓csv做分)。

你可以寫,因此

if line[0] in ('Town 2', 'Town 4'): 

這一點我想你會同意更容易閱讀,少重複輸入,特別是如果你繼續添加更多的城鎮。

0

它可以打開供讀取和使用模式寫入文件「R +」

data = [] 
with open("temp", "r+") as inFile: 
    for line in inFile: 
     ar = line.split(",") 
     if ar[0] in ("Town 2", "Town 4"): 
      data.append((ar[0], int(ar[1]) - 20, "\n")) 
     else: 
      data.append(ar) 

    inFile.seek(0) 
    for d in data: 
     inFile.write(",".join([str(x) for x in d])) 
    inFile.truncate() 

爲了保持一切乾淨,我倒回文件中使用SEEK(0),寫每看完後從緩衝區重新回到該文件中,並在關閉文件之前截斷文件的其餘部分。我很想知道這些操作是否和何時不是必需的。

此變體不會修改(clobber)目錄中的任何其他文件,這對於代碼可能同時在不同輸入文件中同時運行的情況有益。我不知道一次打開一個文件是否有任何性能方面的好處,但它可能在很小的程度上。

相關問題