#1 楼
不幸的是,没有重写就无法插入文件中间。如先前的张贴者所指出的,您可以将文件追加到文件中或使用“搜索”覆盖文件的一部分,但是如果要在文件的开头或中间添加内容,则必须重写它。此是操作系统的东西,而不是Python的东西。在所有语言中都是相同的。
我通常要做的是从文件中读取,进行修改并将其写到名为myfile.txt.tmp的新文件中。这比将整个文件读入内存要好,因为文件可能太大了。临时文件完成后,我将其重命名为原始文件。
这是一种很好的安全方法,因为如果文件写入由于任何原因而崩溃或中止,您仍然可以您未修改的原始文件。
评论
像awk / sed这样的unix工具在代码中是否做类似的事情?
– Manish Gill
13年3月22日在19:16
并非所有语言都一样。在ActionScript中:fileStream.openAsync(filename,FileMode.UPDATE);然后,我可以在文件中的任意位置进行更改。
– AndrewBenjamin
2014年7月11日在3:58
@AndrewBenjamin您知道ActionScript正在制作什么系统吗? openAsync是否有可能在调用之后读取文件并写入一个新文件?
– AlexLordThorsen
2014年12月2日在22:23
@Rawrgulmuffins我不知道。但是,我确实知道它不会将整个文件读入内存,因为我已经使用它来处理几GB的文件大小。我怀疑这与使用C#Streamwriter编写相同。我认为python是一种快速完成小事情的工具,而不是大规模开发和文件操作的工具。
– AndrewBenjamin
15年3月26日在21:48
@AndrewBenjamin,用户并没有要求在文件中四处寻找和更改它(我所知道的每种语言都可以做到这一点);他询问的是插入文本,这与简单地更改/覆盖文件中已有的内容不同。也许在实际应用中它有所不同,但是我在ActionScript API中找不到任何东西表明它在这方面与任何其他语言都不同。
– esstrada
15年7月22日在14:44
#2 楼
取决于您要做什么。要追加,可以用“ 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
评论
只是一小部分,要在Python 2.5中使用with语句,您需要添加“ from future import with_statement”。除此之外,与手动关闭相比,使用with语句打开文件绝对更具可读性,并且不易出错。
–亚历山大·科耶夫尼科夫(Alexander Kojevnikov)
08年9月24日在6:48
您可能会考虑在使用inline = True arg时,fileinput helper lib可以很好地处理脏的open / read / modify / write / replace例程。此处的示例:stackoverflow.com/a/2363893/47390
–mikegreenberg
2012年2月1日在21:14
只是不要忘记关闭文件。 f。关闭()
–D.Rosado
2012年5月2日14:35
我使用的不是D.Rosado样式,但是使用with样式时,我认为您无需手动关闭。 with跟踪其创建的资源。
–克里斯
2012年5月14日17:47
您不需要手动关闭文件。这就是在此处使用“ with”的全部意义。 (实际上,Python会在文件对象被垃圾回收后立即执行此操作,这在CPython中会在绑定到该对象的名称超出范围时发生……但是其他实现则不会,并且CPython可能有一天会停止这样做,因此建议使用“ with”)
–于尔根·艾哈德(JürgenA. Erhard)
13年6月22日在11:16
#3 楼
如果您使用inplace = 1参数,则Python标准库的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
评论
这在python3中应该如何工作?我只是将一个具有这样的代码的应用程序从python移植到了python3,而我根本无法正常工作。 'line'变量是字节类型,我尝试将其解码为unicode,然后对其进行修改,然后再将其编码回字节,但它无法正常工作。这引起了一些我记不住脑海的异常。人们在python3中使用fileinput inplace = 1成功吗?
– robru
2015年2月21日在5:08
@Robru:这是Python 3代码
– jfs
16 Dec 19'在8:02
但这没问题,因为您首先在不重要的文件上对其进行了测试,对吗?
– Paula Livingstone
17年11月18日在13:55
#4 楼
通常,通过使用修改后的名称保存旧副本来原地重写文件。 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+"~" )
评论
看起来不错。想知道.readlines()是否比迭代源更好?
– bozdoz
13年4月10日在15:48
@bozdoz:因为readlines读取整个文件,所以迭代更好。不适用于大文件。当然,这假定您可以以这种本地化的方式进行修改。有时您做不到,或者您的代码变得更加复杂。
–于尔根·艾哈德(JürgenA. Erhard)
13年6月22日在11:20
@ S.Lott:os.rename(aFile,aFile +“〜”)将修改源文件的名称,而不创建副本。
–Patapoom
3月12日9:39
#5 楼
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-这可能会很大。
#6 楼
正如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'\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()
#7 楼
编写了一小堂课,干净利落地做这件事。评论
这对我个人而言不起作用,它确实向文件中添加了文本,但它首先删除了所有内容!
–布雷特·霍克(Bret Hawker)
19年1月12日在19:47
确实,这根本不起作用。丢脸,因为这似乎是个好主意。
–马里奥(MarioKrušelj)
19年6月14日在9:39
#8 楼
如果您知道某些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,检查一下,它非常有用。
评论
根本不是Pythonic
– DarkSuniuM
19年5月27日在1:02
评论
您可以参考Alex Martelli的答案。stackoverflow.com/a/4358169/538284
在python中的csv文件的最上一行上写入的可能重复项
@Ani,另一则帖子无论如何都是在文本文件的指定位置插入行的重复,并且肯定在这里有清晰明确的答案,为什么不在这里添加答案呢?接受答案不是一个好问题的要求。
@BhargavRao投票已撤回。我应该已经找到了重复的东西!