我正在使用Python,并希望在不删除或复制文件的情况下将字符串插入文本文件。我该怎么做呢?
当前回答
不幸的是,没有办法在不重写文件的情况下插入到文件中间。正如之前的海报所指出的,你可以使用seek附加到一个文件或覆盖它的一部分,但如果你想在开始或中间添加东西,你必须重写它。
这是操作系统的问题,不是Python的问题。这在所有语言中都是一样的。
我通常会从文件中读取,进行修改,并将其写入一个名为myfile.txt.tmp的新文件或类似的文件。这比将整个文件读入内存要好,因为文件可能太大了。临时文件完成后,我将其重命名为与原始文件相同的名称。
这是一种很好的、安全的方法,因为如果文件写入由于任何原因崩溃或中止,您仍然拥有原始文件。
其他回答
不幸的是,没有办法在不重写文件的情况下插入到文件中间。正如之前的海报所指出的,你可以使用seek附加到一个文件或覆盖它的一部分,但如果你想在开始或中间添加东西,你必须重写它。
这是操作系统的问题,不是Python的问题。这在所有语言中都是一样的。
我通常会从文件中读取,进行修改,并将其写入一个名为myfile.txt.tmp的新文件或类似的文件。这比将整个文件读入内存要好,因为文件可能太大了。临时文件完成后,我将其重命名为与原始文件相同的名称。
这是一种很好的、安全的方法,因为如果文件写入由于任何原因崩溃或中止,您仍然拥有原始文件。
就地重写文件通常是通过用修改过的名称保存旧副本来完成的。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 + "~")
如果你使用inplace=1参数,Python标准库的fileinput模块将会inplace重写文件:
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
正如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()
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 -这可能非常大。
推荐文章
- 如何排序mongodb与pymongo
- 不可变与可变类型
- 列表是线程安全的吗?
- OpenGL 4.1版本的文本渲染技术是怎样的?
- 如何将文件指针(file * fp)转换为文件描述符(int fd)?
- 操作系统。makdirs在我的路径上不理解“~”
- 如何在Django模板中获得我的网站的域名?
- 在django Forms中定义css类
- 如何在Python中scp ?
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy