替换并覆盖而不是附加


102

我有以下代码:

import re
#open the xml file for reading:
file = open('path/test.xml','r+')
#convert to string:
data = file.read()
file.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data))
file.close()

我想用新内容替换文件中的旧内容。但是,当我执行代码时,将附加文件“ test.xml”,即,我的旧内容被新的“替换”内容所取代。为了删除旧内容而只保留新内容,我该怎么办?



当您说“用新内容替换文件中的旧内容”时,您需要读入并转换当前内容data = file.read()。您的意思不是“无需先阅读就盲目地覆盖它”。
smci

Answers:


112

您需要seek先写入文件的开头,然后再使用(file.truncate()如果要进行就地替换):

import re

myfile = "path/test.xml"

with open(myfile, "r+") as f:
    data = f.read()
    f.seek(0)
    f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))
    f.truncate()

另一种方法是读取文件,然后使用再次打开它open(myfile, 'w')

with open(myfile, "r") as f:
    data = f.read()

with open(myfile, "w") as f:
    f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))

无论是truncateopen(..., 'w')将改变inode的文件的数量(我测试过两次,一次是与Ubuntu 12.04 NFS和曾经与EXT4)。

顺便说一句,这与Python并没有真正的关系。解释器调用相应的低级API。该方法truncate()在C编程语言中的工作原理相同:请参见http://man7.org/linux/man-pages/man2/truncate.2.html


Neither truncate nor open(..., 'w') will change the inode number of the file它为什么如此重要?
韩国

@rok在大多数情况下是否与inode无关。仅在使用硬链接的极端情况下,但我建议您避免使用硬链接
guettli

71
file='path/test.xml' 
with open(file, 'w') as filetowrite:
    filetowrite.write('new content')

以“ w”模式打开文件,您将能够替换其当前文本,并使用新内容保存文件。


6
这是清除文件并为其添加新内容的好方法,但是问题是关于读取文件,修改内容以及用新内容覆盖原始内容。
鲍里斯(Boris)

1
@Boris,先读取文件然后在此答案中使用代码有什么问题?
Rayhunter

@Rayhunter:效率低下
serv-inc

简单高效,以完美的方式完成工作。
Chikku Jacob

16

使用truncate(),解决方案可能是

import re
#open the xml file for reading:
with open('path/test.xml','r+') as f:
    #convert to string:
    data = f.read()
    f.seek(0)
    f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data))
    f.truncate()

1
seek truncate!我不知道为什么seek一个人都不工作。
conner.xyz

2
import os#must import this library
if os.path.exists('TwitterDB.csv'):
        os.remove('TwitterDB.csv') #this deletes the file
else:
        print("The file does not exist")#add this to prevent errors

我遇到了类似的问题,没有使用不同的“模式”覆盖现有文件,而是在再次使用该文件之前删除了该文件,这样就好像我在每次运行代码时都将其追加到新文件上一样。



0

使用python3 pathlib库:

import re
from pathlib import Path
import shutil

shutil.copy2("/tmp/test.xml", "/tmp/test.xml.bak") # create backup
filepath = Path("/tmp/test.xml")
content = filepath.read_text()
filepath.write_text(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", content))

使用不同方法进行备份的类似方法:

from pathlib import Path

filepath = Path("/tmp/test.xml")
filepath.rename(filepath.with_suffix('.bak')) # different approach to backups
content = filepath.read_text()
filepath.write_text(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", content))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.