2017-02-24 40 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)目录中的任何其他文件,这对于代码可能同时在不同输入文件中同时运行的情况有益。我不知道一次打开一个文件是否有任何性能方面的好处,但它可能在很小的程度上。

相关问题