【问题标题】:How to seek write pointer in append mode?如何在附加模式下寻找写指针?
【发布时间】:2020-12-12 14:07:46
【问题描述】:

我正在尝试打开一个文件,读取它的内容并使用之前读取的内容写入它。我以“a+”模式打开文件。我不能使用 'r+' 模式,因为如果文件不存在,它不会创建文件。

【问题讨论】:

  • 如果您知道如何使用r+ 解决它,为什么不在该部分之前使用os.path.exists() 检查文件是否存在,如果不存在则create 它。
  • @Thymen 我现在正在做,但我想知道你怎么能做到这一点。在某些情况下它会很有用。

标签: python-3.x file-handling


【解决方案1】:

a+ 会将指针放在文件末尾。

您可以使用tell() 保存以供以后编写。

然后使用seek(0,0)返回文件开头进行读取。

tell()

seek()

【讨论】:

  • 我找不到这些函数的任何文档,你能指点我吗?谢谢。
  • 我错误地将其称为 C fseek 和 ftell。在 python 中它只是seektell。添加文档链接
  • 在“a+”模式下,它们只操作读取指针。我想控制我在哪里写作。
  • 没有读指针或写指针。只是从读取或写入开始的指针
  • 好吧,我想我在测试时犯了一个错误。
【解决方案2】:

默认开启

使用默认的a(+) 选项是不可能的,如文档中所提供:

''mode 是一个可选字符串,它指定文件的模式 被打开。它默认为“r”,表示打开以阅读文本 模式。其他常用值是 'w' 用于写入(如果 它已经存在),'x' 用于创建和写入新文件,和 'a' 用于附加(在某些 Unix 系统上,意味着所有写入 不管当前的查找位置如何,都附加到文件的末尾)。''


另类

使用默认打开,这是不可能的。但是我们当然可以创建自己的文件处理程序,当文件不存在时,它将以rr+ 模式创建一个文件。

一个与open(filename, 'r+', *args, **kwargs) 完全一样的最小工作示例是:

import os


class FileHandler:
    def __init__(self, filename, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
        self.filename = filename
        self.mode = mode

        self.kwargs = dict(buffering=buffering, encoding=encoding, errors=errors, newline=newline, closefd=closefd)
        if self.kwargs['buffering'] is None:
            del self.kwargs['buffering']
    def __enter__(self):
        if self.mode.startswith('r') and not os.path.exists(self.filename):
            with open(self.filename, 'w'): pass
        self.file = open(self.filename, self.mode, **self.kwargs)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

现在当你使用以下代码时:

with FileHandler("new file.txt", "r+") as file:
    file.write("First line\n")
    file.write("Second line\n")
    file.seek(0, 0)
    file.write("Third line\n")

它会生成一个新文件new file.txt,当它不存在时,带有上下文:

Third line
Second line

如果您使用open,如果文件不存在,您将收到FileNotFoundError


注意事项

  • 我只在模式以r 开头时创建一个新文件,所有其他文件都按正常的open 函数处理。
  • 出于某种原因,将buffering=None 直接传递给open 函数会导致TypeError: an integer is required (got type NoneType) 崩溃,因此如果它是None,我必须将其从关键字参数中删除。即使根据文档它是默认参数(如果有人知道原因,请告诉我)

编辑

以上代码没有处理以下情况:

file = FileHandler("new file.txt", "r+")
file.seek(0, 0)
file.write("Welcome")
file.close()

为了支持所有open用例,上面的类可以使用__getattr__调整如下:

import os


class FileHandler:
    def __init__(self, filename, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
        self.filename = filename
        self.mode = mode

        self.kwargs = dict(buffering=buffering, encoding=encoding, errors=errors, newline=newline, closefd=closefd)
        if self.kwargs['buffering'] is None:
            del self.kwargs['buffering']

        if self.mode.startswith('r') and not os.path.exists(self.filename):
            with open(self.filename, 'w'): pass
        self.file = open(self.filename, self.mode, **self.kwargs)

    def __enter__(self):
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

    def __getattr__(self, item):
        if hasattr(self.file, item):
            return getattr(self.file, item)
        raise AttributeError(f"{type(self).__name__}, doesn't have the attribute {item!r}")

【讨论】:

    猜你喜欢
    • 2020-06-16
    • 2021-12-07
    • 2021-12-19
    • 2012-12-20
    • 2018-09-06
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多