我正在使用Python,并希望将一个字符串插入到文本文件中,而不需要删除或复制该文件。 我应该如何做到这一点?
我正在使用Python,并希望将一个字符串插入到文本文件中,而不需要删除或复制该文件。 我应该如何做到这一点?
很不幸,没有办法在不重写文件的情况下将内容插入到文件的中间。正如之前的帖子所指出的那样,您可以使用seek在文件末尾追加或覆盖其中一部分内容,但如果您想在开头或中间添加东西,您将不得不重写它。
这是一个操作系统的问题,不是Python的问题。所有语言都是一样的。
我通常会从文件中读取,进行修改并将其写入名为myfile.txt.tmp或类似名称的新文件中。这比将整个文件读入内存更好,因为文件可能过大。完成临时文件后,我将其重命名为原始文件名。
这是一种很好、安全的方法,因为如果文件写入由于任何原因崩溃或中止,您仍然有未受影响的原始文件。
取决于你想要做什么。 要追加,可以使用 "a" 打开:
with open("foo.txt", "a") as f:
f.write("new line\n")
如果您想要在文件中前置一些内容,您需要先从文件中读取:
with open("foo.txt", "r+") as f:
old = f.read() # read everything in the file
f.seek(0) # rewind
f.write("new line\n" + old) # write the new line before
with
语句打开文件肯定比手动关闭更可读且不易出错。 - Alexander Kojevnikovinline=True
参数时,您可以考虑使用fileinput
辅助库,它可以很好地处理脏的打开/读取/修改/写入/替换例程。示例在这里:https://dev59.com/IEnSa4cB1Zd3GeqPRtks#2363893 - mikegreenbergf.truncate()
;否则,最终会在文件末尾得到原始文件中的随机垃圾内容。 - undefinedfileinput
模块可以使用inplace=1参数来就地重写文件:import sys
import fileinput
# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5th
for i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
sys.stdout.write(line.replace('sit', 'SIT')) # replace 'sit' and write
if i == 4: sys.stdout.write('\n') # write a blank line after the 5th line
在原地重写文件通常是通过保存带有修改名称的旧副本来完成的。Unix中添加了~
以标记旧文件。Windows用户会做各种各样的事情-添加.bak或.old-或者完全重命名文件,或将~放在名称的前面。
import shutil
shutil.move(afile, afile + "~")
destination= open(aFile, "w")
source= open(aFile + "~", "r")
for line in source:
destination.write(line)
if <some condition>:
destination.write(<some additional line> + "\n")
source.close()
destination.close()
你可以使用以下方法,而不是shutil
。
import os
os.rename(aFile, aFile + "~")
os.rename(aFile, aFile + "~")
会修改源文件的名称,而不是创建一个副本。 - PatapoomPython的mmap模块可以让您向文件中插入内容。以下示例展示了如何在Unix系统中完成此操作(Windows mmap可能不同)。请注意,这并未处理所有错误情况,您可能会破坏或丢失原始文件。此外,它无法处理Unicode字符串。
import os
from mmap import mmap
def insert(filename, str, pos):
if len(str) < 1:
# nothing to insert
return
f = open(filename, 'r+')
m = mmap(f.fileno(), os.path.getsize(filename))
origSize = m.size()
# or this could be an error
if pos > origSize:
pos = origSize
elif pos < 0:
pos = 0
m.resize(origSize + len(str))
m[pos+len(str):] = m[pos:origSize]
m[pos:pos+len(str)] = str
m.close()
f.close()
也可以在以'r+'模式打开的文件中进行此操作,但这样做不够方便,效率也不高,因为您需要从插入位置到EOF读取并临时存储文件的内容-可能非常大。
正如Adam所提到的,您在决定处理方式之前必须考虑系统的限制,无论是将所有内容都读入内存还是替换部分并重新编写。
如果您正在处理小文件或没有内存问题,这可能会有所帮助:
选项1) 将整个文件读入内存,在整行或部分行上执行正则表达式替换,并将其替换为该行加上额外的行。您需要确保“中间行”在文件中是唯一的,或者如果每行都有时间戳,则这应该是相当可靠的。
# open file with r+b (allow write and binary mode)
f = open("file.log", 'r+b')
# read entire content of file into memory
f_content = f.read()
# basically match middle line and replace it with itself and the extra line
f_content = re.sub(r'(middle line)', r'\1\nnew line', f_content)
# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)
# clear file content
f.truncate()
# re-write the content with the updated content
f.write(f_content)
# close file
f.close()
选项2) 找出中间行,然后用该行加上额外的一行进行替换。
# open file with r+b (allow write and binary mode)
f = open("file.log" , 'r+b')
# get array of lines
f_content = f.readlines()
# get middle line
middle_line = len(f_content)/2
# overwrite middle line
f_content[middle_line] += "\nnew line"
# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)
# clear file content
f.truncate()
# re-write the content with the updated content
f.write(''.join(f_content))
# close file
f.close()
import tempfile
class FileModifierError(Exception):
pass
class FileModifier(object):
def __init__(self, fname):
self.__write_dict = {}
self.__filename = fname
self.__tempfile = tempfile.TemporaryFile()
with open(fname, 'rb') as fp:
for line in fp:
self.__tempfile.write(line)
self.__tempfile.seek(0)
def write(self, s, line_number = 'END'):
if line_number != 'END' and not isinstance(line_number, (int, float)):
raise FileModifierError("Line number %s is not a valid number" % line_number)
try:
self.__write_dict[line_number].append(s)
except KeyError:
self.__write_dict[line_number] = [s]
def writeline(self, s, line_number = 'END'):
self.write('%s\n' % s, line_number)
def writelines(self, s, line_number = 'END'):
for ln in s:
self.writeline(s, line_number)
def __popline(self, index, fp):
try:
ilines = self.__write_dict.pop(index)
for line in ilines:
fp.write(line)
except KeyError:
pass
def close(self):
self.__exit__(None, None, None)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
with open(self.__filename,'w') as fp:
for index, line in enumerate(self.__tempfile.readlines()):
self.__popline(index, fp)
fp.write(line)
for index in sorted(self.__write_dict):
for line in self.__write_dict[index]:
fp.write(line)
self.__tempfile.close()
with FileModifier(filename) as fp:
fp.writeline("String 1", 0)
fp.writeline("String 2", 20)
fp.writeline("String 3") # To write at the end of the file
$ cat my_data.txt
This is a data file
with all of my data in it.
然后使用os
模块,您可以使用通常的sed
命令。
import os
# Identifiers used are:
my_data_file = "my_data.txt"
command = "sed -i 's/all/none/' my_data.txt"
# Execute the command
os.system(command)