82

我需要在文本文件的第一行添加一行,看起来我唯一可用的选项是比我期望的 python 更多的代码行。像这样的东西:

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

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

f.write(temp)
f.close()

没有更简单的方法吗?此外,我看到这个双句柄示例比打开单个句柄进行读写('r+')更常见 - 为什么会这样?

4

11 回答 11

105

Python 使很多事情变得简单,并包含用于许多常见操作的库和包装器,但目标不是隐藏基本事实。

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

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

无论如何都要为自己保存文件句柄,但不要试图将此操作打包成尽可能少的代码行。事实上,永远不要去寻找最少的代码行——那是混淆,而不是编程。

于 2010-12-15T20:24:30.557 回答
84

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

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 中不可用。

于 2010-12-15T20:35:17.930 回答
25

其他方法:

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

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

干杯

于 2010-12-15T20:18:55.310 回答
11
with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)
于 2010-12-15T20:20:47.730 回答
3

您可以使用以下方法保存一个写入调用:

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

使用 'r+' 时,您必须在读取之后和写入之前回退文件。

于 2010-12-15T20:04:30.637 回答
3

这是我认为清晰灵活的 3 班轮。它使用 list.insert 函数,所以如果你真的想添加到文件中,请使用 l.insert(0, 'insert_str')。当我实际为我正在开发的 Python 模块执行此操作时,我使用了 l.insert(1, 'insert_str') 因为我想跳过第 0 行的 '# - - coding: 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()
于 2014-01-04T15:50:39.220 回答
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)
于 2012-06-01T12:48:39.420 回答
0

一种可能性如下:

import os
open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read())
os.rename('tempfile', 'filename')
于 2010-12-15T20:18:11.157 回答
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()

所以首先你打开文件,阅读它并将它全部保存到一个字符串中。然后我们尝试在字符串中查找将发生注入的字符编号。然后通过一次写入和对字符串的一些智能索引,我们现在可以重写整个文件,包括注入的文本。

于 2015-08-27T13:55:59.370 回答
0

我没有看到什么或者我们不能只使用一个足够大的缓冲区来部分(而不是整个内容)读入输入文件,并使用这个缓冲区在文件打开时遍历文件并继续交换文件<- >缓冲区内容?

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

于 2019-06-14T07:33:05.510 回答
0

正如我在答案中建议的那样,您可以使用以下方法进行操作:

def prepend_text(filename: Union[str, Path], text: str):
    with fileinput.input(filename, inplace=True) as file:
        for line in file:
            if file.isfirstline():
                print(text)
            print(line, end="")
于 2022-01-05T10:18:54.407 回答