Python os.ftruncate() 方法(完整教程)

什么是 Python os.ftruncate() 方法?

在 Python 的文件操作中,我们经常需要对文件进行读写、追加、删除等操作。但你是否遇到过这样的场景:某个文件太大,但实际内容只占很小一部分,而你又想快速“截断”它,只保留前面有用的部分?这时,os.ftruncate() 方法就派上用场了。

Python os.ftruncate() 方法 是一个底层的系统级操作,它允许你直接修改打开文件的大小,而不需要读取或写入整个文件内容。它的作用就像一把“文件尺寸裁剪刀”——你可以把一个大文件“剪短”到你想要的长度,也可以把它“拉长”(不过拉长时会填充空字节)。

这个方法特别适合处理日志文件、缓存文件、数据库临时文件等需要动态管理大小的场景。它不依赖于 Python 的文件对象,而是直接与操作系统交互,效率极高。

⚠️ 注意:使用 os.ftruncate() 时,你必须已经通过 os.open()open() 打开了文件,并且拿到了文件描述符(file descriptor)。它不能直接作用于普通的文件对象。


如何使用 Python os.ftruncate() 方法?

我们先来看一个最基础的使用方式。假设你有一个名为 example.txt 的文件,里面的内容是:

Hello, this is a test file.
It has multiple lines.
We will truncate it later.

现在我们想把这个文件截断到只保留前 20 个字节的内容。下面是如何实现的:

import os

fd = os.open("example.txt", os.O_RDWR)

os.ftruncate(fd, 20)

os.close(fd)

print("文件已成功截断至 20 字节。")

✅ 注释说明:

  • os.open() 返回一个整数文件描述符(fd),是操作系统层面的句柄。
  • os.ftruncate(fd, 20) 会把文件大小强制设为 20 字节。
  • os.close(fd) 是必须的,否则文件资源可能泄漏。

运行这段代码后,example.txt 文件内容将变为:

Hello, this is a test 

注意:它只保留了前 20 个字节,后面的字符全部被“剪掉”。


截断文件的两种常见场景

场景一:缩短文件,清理多余内容

当你处理日志文件时,可能希望只保留最近 100KB 的记录,旧的日志自动丢弃。这时,os.ftruncate() 是最高效的方式。

import os

def truncate_log_file(filename, max_size_bytes):
    """截断日志文件,只保留指定大小的内容"""
    try:
        # 打开文件获取文件描述符
        fd = os.open(filename, os.O_RDWR)
        
        # 获取当前文件大小
        current_size = os.fstat(fd).st_size
        
        # 如果文件大小超过限制,则截断
        if current_size > max_size_bytes:
            os.ftruncate(fd, max_size_bytes)
            print(f"文件 {filename} 已截断至 {max_size_bytes} 字节。")
        else:
            print(f"文件 {filename} 大小为 {current_size} 字节,无需截断。")
            
        os.close(fd)
        
    except Exception as e:
        print(f"截断文件时出错:{e}")

truncate_log_file("app.log", 1024)  # 限制为 1KB

✅ 注释说明:

  • os.fstat(fd) 获取文件的状态信息,.st_size 是文件大小(字节)。
  • 这个函数可以安全地处理大文件,不会加载整个文件到内存。

场景二:扩展文件,预分配空间

有时候你希望创建一个大文件,但不立即写入内容,比如用于数据库或缓存。你可以用 os.ftruncate() 把文件“拉长”,系统会自动填充空字节(\x00)。

import os

filename = "large_file.bin"
size_in_bytes = 1024 * 1024  # 1MB

fd = os.open(filename, os.O_CREAT | os.O_RDWR, 0o644)

os.ftruncate(fd, size_in_bytes)

os.close(fd)

print(f"已创建 {filename},大小为 {size_in_bytes} 字节。")

✅ 注释说明:

  • os.O_CREAT 表示如果文件不存在则创建。
  • 0o644 是文件权限(类似 Linux 的 rwxr--r--)。
  • 文件创建后,系统会自动填充 0x00 字节,直到达到指定大小。

常见陷阱与注意事项

陷阱一:文件描述符未关闭

忘记调用 os.close(fd) 会导致资源泄漏,尤其是在循环或长时间运行的程序中。建议使用 with 语句来确保关闭。

import os

filename = "test.txt"
size = 50

try:
    with os.open(filename, os.O_RDWR) as fd:
        os.ftruncate(fd, size)
        print(f"文件已截断至 {size} 字节。")
except Exception as e:
    print(f"操作失败:{e}")

✅ 注释说明:

  • with os.open(...) 会自动在代码块结束时调用 os.close(fd),非常安全。

陷阱二:截断位置不准确

os.ftruncate() 的参数是字节数,而不是字符数。中文字符(如“你好”)在 UTF-8 编码中占 3 字节,所以要小心。

import os

text = "你好世界"  # 4 个字符,共 12 字节
with open("test_chinese.txt", "w", encoding="utf-8") as f:
    f.write(text)

fd = os.open("test_chinese.txt", os.O_RDWR)
os.ftruncate(fd, 6)
os.close(fd)

with open("test_chinese.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(f"截断后内容:{content}")  # 输出:你好

✅ 注释说明:

  • 即使你只写了 4 个汉字,截断到 6 字节后,只会保留前两个汉字,第三个字符“世”被截断,可能造成乱码。

os.ftruncate() 与 Python 内置文件操作的对比

操作方式 是否需要读取文件 是否影响性能 适用场景
os.ftruncate() 非常快,O(1) 大文件截断、预分配空间
file.seek(0); file.truncate() 是(需读取) 依赖文件大小,慢 小文件、文本处理
手动读写再写入 极慢 不推荐,除非特殊需求

✅ 总结:对于大文件操作,os.ftruncate() 是唯一高效的选择。它直接与操作系统交互,不经过 Python 的 I/O 缓冲层。


实际项目中的最佳实践

在实际开发中,建议将 os.ftruncate() 封装成工具函数,避免重复代码:

import os
from pathlib import Path

def safe_truncate_file(filepath, size_bytes):
    """
    安全地截断文件,支持路径对象
    :param filepath: 文件路径(str 或 Path)
    :param size_bytes: 目标大小(字节)
    """
    path = Path(filepath)
    if not path.exists():
        print(f"文件不存在:{filepath}")
        return False

    try:
        with os.open(path, os.O_RDWR) as fd:
            # 先获取当前大小,避免无效操作
            current_size = os.fstat(fd).st_size
            if current_size <= size_bytes:
                print(f"文件大小 {current_size} ≤ {size_bytes},无需截断。")
                return True
            os.ftruncate(fd, size_bytes)
            print(f"成功截断 {path} 至 {size_bytes} 字节。")
        return True
    except Exception as e:
        print(f"截断失败:{e}")
        return False

safe_truncate_file("data.bin", 1024 * 100)  # 截断到 100KB

✅ 注释说明:

  • 使用 Path 更加现代和安全。
  • 增加了存在性检查和大小比较,避免无意义操作。

总结

Python os.ftruncate() 方法 是一个强大但常被忽视的底层工具。它能让你以极低的开销完成文件大小的精确控制,尤其适合处理大文件、日志管理、缓存预分配等场景。

虽然它的使用门槛略高于普通文件操作,但一旦掌握,你会发现在性能敏感的应用中,它能带来质的飞跃。记住:不要总是用读写来“删”文件,有时候“剪”一下更高效

无论是缩短文件清理冗余,还是扩展文件预分配空间,os.ftruncate() 都是值得掌握的利器。下次你再遇到“文件太大,但只想留一部分”的问题时,不妨试试这个方法。