在Python的现有文件前添加一行


73

我需要在文本文件的第一行中添加一行,并且看来对我唯一可用的选项是比我从python期望的更多行。像这样:

f = open('filename','r')
temp = f.read()
f.close()

f = open('filename', 'w')
f.write("#testfirstline")

f.write(temp)
f.close()

有没有更简单的方法?另外,与打开单个手柄进行读写('r +')相比,我更经常看到此两个手柄的示例-为什么?


1
(值得注意的是:您最好逐行读取文件并写入临时文件。完成后,删除原始文件并替换为临时文件。)
cwallenpoole

Answers:


95

Python使许多事情变得容易,并包含许多常见操作的库和包装器,但目标并非隐藏基本事实。

您在这里遇到的基本事实是,通常无法在不重写整个结构的情况下将数据放在现有的平面结构之前。无论语言如何,都是如此。

有一些方法可以保存文件句柄或使代码的可读性降低,其中许多方法是在其他答案中提供的,但是没有一种方法可以改变基本操作:必须先读取现有文件,然后写出要添加的数据,然后再输入您读入的现有数据。

一定要保存文件句柄,但不要试图将此操作打包到尽可能少的代码行中。实际上,永远不要去寻找最少的代码行-就是混淆,而不是编程。


35
“永远不要去寻找最少的代码行-就是混淆,而不是编程”-隐藏执行功能所花费的时间并不是混淆,而是抽象。如果代码的目的是花费一定比例的时间来阅读和运行代码,那么它的结构将与实际结构完全不同。
Aviendha

“您必须先读入现有文件,然后写出要添加的数据,然后再写入读入的现有数据”-这不是真的,因为对读入的数据进行块化和交错处理可以节省更多内存,编写操作,以便文件的全部内容永远不需要一次驻留在内存中。实际上,处理这些细节将成为一个出色的库。
肯·威廉姆斯

73

我会坚持使用单独的读取和写入,但是我们当然可以更简洁地表达它们:

Python2:

with file('filename', 'r') as original: data = original.read()
with file('filename', 'w') as modified: modified.write("new first line\n" + data)

Python3:

with open('filename', 'r') as original: data = original.read()
with open('filename', 'w') as modified: modified.write("new first line\n" + data)

注意:file()函数在python3中不可用。


1
请注意,file()-function在Python 3中不可用,仅在版本2中可用。只需open()在Python 3
中将

7
实际上,您也不应该在Python 2中使用file函数。您应该始终使用open()任一Python中的函数打开文件。仅出于历史原因,才提供文件功能。
Henry Schreiner

@HenrySchreiner当时,我认为这file更直观,无论社区达成共识和通用的样式准则如何。但是当3.x出现时(我是一个非常渴望采用FWIW的人),我没有其他选择了:)
Karl Knechtel 2015年

24

其他方法:

with open("infile") as f1:
    with open("outfile", "w") as f2:
        f2.write("#test firstline")
        for line in f1:
            f2.write(line)

或一个班轮:

open("outfile", "w").write("#test firstline\n" + open("infile").read())

感谢您有机会考虑这个问题:)

干杯


9
with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)

3

您可以使用以下命令保存一个写调用:

f.write('#testfirstline\n' + temp)

使用“ r +”时,您必须在读取后和写入前倒回文件。


2
+1,尽管您这样做可以保存一整行代码f.write('#testfirstline\n' + temp)
mtrw 2010年

5
我会推荐f.writelines(('#testfirstline\n',tmp))。然后,如果temp很大,则无需创建另一个巨大的字符串即可将其全部写出。或者,只是使用额外的写行作为OP ...
贾斯汀·皮尔

3

我认为这是3衬板,清晰灵活。它使用list.insert函数,因此,如果您确实想在文件前添加l.insert(0,'insert_str')。当我为正在开发的Python模块实际执行此操作时,我使用了l.insert(1,'insert_str'),因为我想跳过第0行的'#--encoding :utf- 8-- '字符串。这是编码。

f = open(file_path, 'r'); s = f.read(); f.close()
l = s.splitlines(); l.insert(0, 'insert_str'); s = '\n'.join(l)
f = open(file_path, 'w'); f.write(s); f.close()

您也可以将其制成1排
Shadi

这个打印出汉字!
乌尔夫·杰丁根

2
嗨,Ulf Gjerdingen!文件中是否包含汉字?
爱与和平-乔·考兹威尔(Joe Codeswell)

2

尽管它可能无法在Windows上运行,但无需将整个文件读入内存即可完成此工作

def prepend_line(path, line):
    with open(path, 'r') as old:
        os.unlink(path)
        with open(path, 'w') as new:
            new.write(str(line) + "\n")
            shutil.copyfileobj(old, new)

我喜欢这个,尽管您必须小心,否则如果中断会导致数据丢失。
2015年

这样做将覆盖文件。是否可以使用shutil.copyfileobj而不是覆盖来创建新文件?
alvas 2015年

1
抱歉@alvas我不太明白你的意思。如果您要写入新文件,只需path在的第二个调用中输入一个不同的名称即可open
2016年

0

一种可能性如下:

import os
open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read())
os.rename('tempfile', 'filename')

2
这在POSIX上是不安全的(我相信某些文件系统的竞争条件,XFS)。在重命名之前,需要在临时文件上调用f.flush()和os.fsync(f.fileno())。
Rosh Oxymoron 2010年


0

如果您希望在文件后加上特定文字,则可以使用以下功能。

def prepend_text(file, text, after=None):
    ''' Prepend file with given raw text '''
    f_read = open(file, 'r')
    buff = f_read.read()
    f_read.close()
    f_write = open(file, 'w')
    inject_pos = 0
    if after:
        pattern = after
        inject_pos = buff.find(pattern)+len(pattern)
    f_write.write(buff[:inject_pos] + text + buff[inject_pos:])
    f_write.close()

因此,首先打开文件,阅读并保存到一个字符串中。然后,我们尝试在将要进行注入的字符串中找到字符号。然后通过一次写入和对该字符串的一些智能索引,我们现在可以重写整个文件,包括注入的文本。


0

我不能看到的东西还是不能我们只是使用缓冲区足够大的读取,输入文件中的部分(而不是全部内容),并与该缓冲区遍历文件,同时它是开放的,并保持交换文件< - >缓冲区内容?

这似乎比读取内存中全部内容,修改内存中的内容并将其写回到同一文件或(甚至更糟)另一个文件要有效得多(尤其是对于大文件)。抱歉,现在我没有时间实施示例代码段,我稍后再讲,但也许您明白了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.