如何修改文本文件?

我正在使用Python,并希望插入一个string到文本文件而不删除或复制文件。 我怎样才能做到这一点?

不幸的是,没有重写它,没有办法插入到文件的中间。 正如之前的海报所表明的,你可以附加到一个文件或使用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 

如果使用inplace = 1参数,则Python标准库的fileinput模块将重写fileinput文件:

 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+"~" ) 

Python的mmap模块将允许你插入一个文件。 以下示例显示了如何在Unix中完成(Windows mmap可能不同)。 请注意,这不会处理所有的错误情况,您可能会损坏或丢失原始文件。 而且,这不会处理Unicodestring。

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

也可以在不使用mmap的情况下以“r +”模式打开文件,但是它不太方便,效率也不高,因为您必须读取文件的内容并将其从插入位置临时存储到EOF,是巨大的。

正如亚当所说,你必须考虑系统的限制,然后才能决定是否有足够的内存将其全部读取到内存中,并将其重新写入内存。

如果你正在处理一个小文件或没有内存问题,这可能会有所帮助:

选项1)将整个文件读入内存,在整个或部分行上执行正则expression式replace,并用该行加上额外的行replace它。 您需要确保“中间线”在文件中是唯一的,或者每行都有时间戳,这应该是非常可靠的。

 # 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)找出中间行,并用该行加上额外的行replace它。

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

写了一个小class干净的做这个。

 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