如何打开(读写)或创建允许截断的文件?

2024-04-25 07:05:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我想:

  • 以读写模式打开文件(如果存在)
  • 如果它不存在就创造它
  • 可以随时随地截短它。

编辑:对于truncate,我的意思是写到某个位置,并丢弃文件的剩余部分(如果存在)

所有这些都是原子式的(使用单个open()调用或模拟单个open()调用)

似乎没有单一的开放模式适用:

  • r:显然不行
  • r+:如果文件不存在,则失败
  • w: 如果文件存在,请重新创建该文件
  • w+:如果文件存在,则重新创建该文件
  • a: 不能阅读
  • a+:无法截断。

我尝试的一些组合(r w、rw+、r+w等)似乎也不起作用。有可能吗?

Ruby中的一些doc(也适用于python):

r
Read-only mode. The file pointer is placed at the beginning of the file.
This is the default mode.

r+
Read-write mode. The file pointer will be at the beginning of the file.

w
Write-only mode. Overwrites the file if the file exists. If the file
does not exist, creates a new file for writing.

w+
Read-write mode. Overwrites the existing file if the file exists. If the
file does not exist, creates a new file for reading and writing.

a
Write-only mode. The file pointer is at the end of the file if the file
exists. That is, the file is in the append mode. If the file does not exist,
it creates a new file for writing.

a+
Read and write mode. The file pointer is at the end of the file if the file
exists. The file opens in the append mode. If the file does not exist, it
creates a new file for reading and writing.

Tags: 文件ofthereadifismodeexists
3条回答

根据OpenGroup

O_TRUNC

If the file exists and is a regular file, and the file is successfully opened O_RDWR or O_WRONLY, its length is truncated to 0 and the mode and owner are unchanged. It will have no effect on FIFO special files or terminal device files. Its effect on other file types is implementation-dependent. The result of using O_TRUNC with O_RDONLY is undefined.

所以,打开“w”或“w+”文件时可能会传递O_TRUNC。这给了“截断”一个不同的含义,不是我想要的。

使用python,解决方案似乎是使用os.open()函数以低级别I/O打开文件。

以下python函数:

def touchopen(filename, *args, **kwargs):
    # Open the file in R/W and create if it doesn't exist. *Don't* pass O_TRUNC
    fd = os.open(filename, os.O_RDWR | os.O_CREAT)

    # Encapsulate the low-level file descriptor in a python file object
    return os.fdopen(fd, *args, **kwargs)

有我想要的行为。你可以这样使用它(实际上这是我的用例):

# Open an existing file or create if it doesn't exist
with touchopen("./tool.run", "r+") as doing_fd:

    # Acquire a non-blocking exclusive lock
    fcntl.lockf(doing_fd, fcntl.LOCK_EX)

    # Read a previous value if present
    previous_value = doing_fd.read()
    print previous_value 

    # Write the new value and truncate
    doing_fd.seek(0)
    doing_fd.write("new value")
    doing_fd.truncate()

您可以用“a+”(Ruby)读、写和截断:

File.open("test.txt", "a+") do |f|
  f.print "abc\ndefgh" 
  f.rewind
  p f.read 
  f.truncate(5) 
end
puts File.size("test.txt") #=> 5

好吧,只有这些模式,它们都有你列出的“缺陷”。

你唯一的选择是包装open()。 为什么不做这样的事?(Python)

def touchopen(filename, *args, **kwargs):
    open(filename, "a").close() # "touch" file
    return open(filename, *args, **kwargs)

它的行为就像open一样,如果您真的愿意,甚至可以将其重新绑定到open()。

open的所有功能都被保留,您甚至可以执行以下操作:

with touchopen("testfile", "r+") as testfile:
    do_stuff()

当然,您可以创建一个contextmanager,它以+模式打开文件,将其读入内存,并截取写操作,以便通过在w模式下神奇地创建一个临时文件来处理截断,并在关闭时将该临时文件重命名为原始文件,但我想这可能是过分了。

相关问题 更多 >