未将字符串替换写入文件

时间:2019-05-23 03:49:17

标签: python string python-2.7 replace io

我需要编辑特定文件才能进行DoE研究。该文件的格式为:

1 Wall1
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
2 Wall2
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
3 Wall3
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
4 Wall4
roughness 0.0
velocity 0.0
temperature 34.1
########
5 Roof
roughness 0.0
velocity 0.0
temperature "temperature.file"
########

对于DoE,我想针对每种情况更改一个或多个“ temperature.file”条目(这是一个区域的空间变化温度场)。因此,例如,情况2会将Wall2的温度文件更改为“ temperature2.file”。然后程序将知道要查找新文件而不是原始文件。

我已经建立了嵌套的for循环,但是在文件I / O方面很挣扎。我现在拥有的代码是:

if m == 2:
    with open(newfolder2+'/walls.in','r') as file:
        filedata = file.readlines()
        for line in filedata:
            if 'Wall2' in line:
                for line in filedata:
                    if 'temperature' in line:
                        print line
                        line = line.replace('temperature.file','temperature2.file')
                        print line
                        break
#       file.seek(0)

    with open(newfolder2+'/walls.in','w') as file:
        file.writelines(filedata)

所以从本质上讲,我想找到“ Wall2”所在的行,然后在Wall2之后查找带有温度的行,然后将其更改,只有该行的“ temperature.file”字符串更改为“ temperature2.file”。然后退出文件,然后写入文件,从而为该特定情况创建新的输入文件。

我拥有的第一条打印行确实打印出了原始行,第二条打印行代码也正确地打印出了更改过的行。但是,似乎文件数据没有成功写回到文件中。

似乎出了什么问题?

我认为,另一种方法不是使用所有嵌套循环来查找特定行,而是仅使用file.seek()选项。 wall.in文件的行和总长度将保持不变,因此我可以直接转到该特定行以更改“ temperature.in”字符串。这是更好的方法吗?我从来没有尝试过,所以一些示例代码将不胜感激。

非常感谢大家!

3 个答案:

答案 0 :(得分:0)

当您遍历各行时,所获得的是原始行的副本。

您可以做的就是这样,将文件的内容分成多个部分。由于文件中的每个部分都以########结尾,因此我们可以使用它来将文件拆分为多个块。然后,您可以更改找到的块并将其写回到文件数据中,然后再保存。

with open(newfolder2+'/walls.in', 'r') as file:
filedata = file.read().split("########")
for i, chunk in enumerate(filedata):
    if "Wall2" in chunk:
        chunk = chunk.replace('temperature.file', 'temperature2.file')
        filedata[i] = chunk

with open(newfolder2+'/walls.in', 'w') as file:
    file.writelines("########".join(filedata))

答案 1 :(得分:0)

您绝不会为filedata分配任何新内容。

您可以编写类似解析器的工具来了解上下文(这里是您所在的墙号)。这可能看起来像这样:

from io import StringIO

# thie u is needed in python < 3
txt = u"""1 Wall1
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
2 Wall2
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
"""

wall = None
with StringIO(txt) as infile, StringIO() as outfile:
    for line in infile:
        if " Wall" in line:
            wall = int(line[:2])
        if wall == 2:
            if '"temperature.file"' in line:
                line = line.replace('"temperature.file"', '"temperature2.file"')
        outfile.write(line)

    print(outfile.getvalue())

要真正读/写文件,您必须使用{p>更改with

with open(newfolder2+'/walls.in','r') as infile, 
     open(newfolder2+'/walls.out','w') as outfile:

,然后删除包含outfile.getvalue()的行。然后必须将walls.out重命名为walls.in。这样,如果程序执行了您不想要的操作,您的原始文件就不会丢失。

如果您想为其他Wall更改其他行,这可能很容易适应。

答案 2 :(得分:0)

这里发生了两个错误。

  1. 当您在for循环中进行迭代时,更改的变量将在本地初始化,而更改实际上并不会更改被循环的对象。
>>> a = [5,4,3,7,1]
>>> for i in a:
...     i=2  # this won't change the elements of a!
... 
>>> a
[5, 4, 3, 7, 1]
  1. 按照其结构方式,第二个for循环将在找到filedata之后从头开始在Wall2上进行迭代。这是因为for循环本身并不知道它正在另一个for循环中运行。即使您修复了1,也将最终得到错误的结果。要么使用迭代器在filedata上循环,要么使用f.readline()本身就是一个生成器。
filedata=iter(filedata)

以下代码应该起作用:

filedata = []
with open('myfile') as f:
    line = ''
    while 'Wall2' not in line:
        line = f.readline()
        filedata.append(line)
    while 'temperature' not in line:
        line = f.readline()
        filedata.append(line)
    filedata.append(line.replace('temperature.file','temperature2.file'))

with open('myfile', 'w') as f:
    f.writelines(filedata)

但是我不会这样做。如果您知道文件始终采用相同的格式,并且行号始终保持不变,请使用file.seek。它应该快得多。如果要在适当的位置修改文件,另请参见Is it possible to modify lines in a file in-place?