我正在使用Python,并希望在不删除或复制文件的情况下将字符串插入文本文件。我该怎么做呢?


当前回答

就地重写文件通常是通过用修改过的名称保存旧副本来完成的。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可能不同)。请注意,这并不能处理所有错误条件,您可能会损坏或丢失原始文件。而且,这不会处理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()

也可以在没有mmap的情况下以'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()

就地重写文件通常是通过用修改过的名称保存旧副本来完成的。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 + "~")

不幸的是,没有办法在不重写文件的情况下插入到文件中间。正如之前的海报所指出的,你可以使用seek附加到一个文件或覆盖它的一部分,但如果你想在开始或中间添加东西,你必须重写它。

这是操作系统的问题,不是Python的问题。这在所有语言中都是一样的。

我通常会从文件中读取,进行修改,并将其写入一个名为myfile.txt.tmp的新文件或类似的文件。这比将整个文件读入内存要好,因为文件可能太大了。临时文件完成后,我将其重命名为与原始文件相同的名称。

这是一种很好的、安全的方法,因为如果文件写入由于任何原因崩溃或中止,您仍然拥有原始文件。

如果你知道一些unix,你可以尝试以下:

注意:$表示命令提示符

假设你有一个my_data.txt文件,内容如下:

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

如果您不了解sed,请查看它,它非常有用。