替换并覆盖而不是附加

问题:替换并覆盖而不是附加

我有以下代码:

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”,即,我的旧内容被新的“替换”内容所取代。为了删除旧内容而只保留新内容,我该怎么办?

I have the following code:

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

where I’d like to replace the old content that’s in the file with the new content. However, when I execute my code, the file “test.xml” is appended, i.e. I have the old content follwed by the new “replaced” content. What can I do in order to delete the old stuff and only keep the new?


回答 0

您需要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

You need seek to the beginning of the file before writing and then use file.truncate() if you want to do inplace replace:

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

The other way is to read the file then open it again with 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))

Neither truncate nor open(..., 'w') will change the inode number of the file (I tested twice, once with Ubuntu 12.04 NFS and once with ext4).

By the way, this is not really related to Python. The interpreter calls the corresponding low level API. The method truncate() works the same in the C programming language: See http://man7.org/linux/man-pages/man2/truncate.2.html


回答 1

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

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

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

Open the file in ‘w’ mode, you will be able to replace its current text save the file with new contents.


回答 2

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

Using truncate(), the solution could be

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

回答 3

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

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

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

I had a similar problem, and instead of overwriting my existing file using the different ‘modes’, I just deleted the file before using it again, so that it would be as if I was appending to a new file on each run of my code.


回答 4

请参阅“如何在文件中替换字符串”,这是一种简单的方法,并且可以解决replace

fin = open("data.txt", "rt")
fout = open("out.txt", "wt")

for line in fin:
    fout.write(line.replace('pyton', 'python'))

fin.close()
fout.close()

See from How to Replace String in File works in a simple way and is an answer that works with replace

fin = open("data.txt", "rt")
fout = open("out.txt", "wt")

for line in fin:
    fout.write(line.replace('pyton', 'python'))

fin.close()
fout.close()

回答 5

使用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))

Using python3 pathlib library:

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

Similar method using different approach to backups:

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