ZetCode

Python os.truncate 函数

上次修改时间:2025 年 4 月 11 日

本全面指南探讨 Python 的 os.truncate 函数,该函数通过截断或扩展文件大小来修改文件。我们将介绍使用场景、权限要求和实际示例。

基本定义

os.truncate 函数将文件大小更改为指定的长度。如果文件被扩展,则新字节将填充零。

关键参数:path (要修改的文件),length (以字节为单位的新大小)。需要对文件具有写入权限。适用于常规文件,不适用于目录。

将文件截断为更小的大小

os.truncate 最常见的用途是通过丢弃超出指定长度的内容来减小文件大小。此示例演示了基本截断。

basic_truncate.py
import os

# Create a sample file
file_path = "data.txt"
with open(file_path, "w") as f:
    f.write("This is some sample text for truncation demonstration.")

# Check original size
original_size = os.path.getsize(file_path)
print(f"Original size: {original_size} bytes")

# Truncate to 20 bytes
os.truncate(file_path, 20)
new_size = os.path.getsize(file_path)
print(f"New size: {new_size} bytes")

# Verify content
with open(file_path) as f:
    print(f"Content: '{f.read()}'")

这会创建一个文件,然后将其截断为 20 字节。剩余内容将是原始文本的前 20 个字节。

请注意,截断会立即在文件系统级别发生,而无需重新打开文件。

用零扩展文件

当指定的长度大于当前文件大小时,os.truncate 会通过填充空字节来扩展文件。此示例显示文件扩展。

extend_file.py
import os

file_path = "empty.dat"

# Create empty file
with open(file_path, "w"):
    pass

# Extend file to 1KB (1024 bytes)
os.truncate(file_path, 1024)
size = os.path.getsize(file_path)
print(f"File size after extension: {size} bytes")

# Verify content is null bytes
with open(file_path, "rb") as f:
    content = f.read(16)  # Read first 16 bytes
    print(f"First 16 bytes: {content}")

这会创建一个空文件,然后将其扩展到 1024 字节。新空间将填充零。二进制模式用于读取空字节。

文件扩展对于预分配空间或创建稀疏文件很有用。

截断打开的文件描述符

os.ftruncate 的工作方式类似,但操作的是打开的文件描述符而不是路径。此示例显示了两个函数以进行比较。

fd_truncate.py
import os

file_path = "log.txt"

# Using os.truncate with path
with open(file_path, "w") as f:
    f.write("Initial content for truncation test")

os.truncate(file_path, 10)
print(f"After path truncate: {os.path.getsize(file_path)} bytes")

# Using os.ftruncate with file descriptor
with open(file_path, "r+") as f:
    fd = f.fileno()
    os.ftruncate(fd, 5)
    print(f"After fd truncate: {os.path.getsize(file_path)} bytes")

这两个函数都实现了相同的结果,但采用不同的参数。 os.ftruncate 需要一个打开的文件描述符。

必须以允许写入的模式打开文件才能使用 os.ftruncate

错误处理

os.truncate 可能会引发各种异常。此示例演示了针对常见场景的正确错误处理。

error_handling.py
import os
import errno

file_path = "protected.txt"

try:
    # Attempt to truncate a non-existent file
    os.truncate("nonexistent.txt", 100)
except FileNotFoundError:
    print("Error: File not found")

try:
    # Attempt to truncate without permissions
    os.truncate("/root/protected.txt", 100)
except PermissionError:
    print("Error: Permission denied")

try:
    # Attempt to truncate a directory
    os.truncate("/tmp", 100)
except IsADirectoryError:
    print("Error: Cannot truncate a directory")

try:
    # Invalid length
    os.truncate(file_path, -1)
except OSError as e:
    if e.errno == errno.EINVAL:
        print("Error: Invalid length specified")

这显示了处理找不到文件、权限问题、目录截断和无效长度参数的情况。 每种情况都会引发不同的异常。

在处理文件系统操作时,始终验证输入并处理潜在的错误。

与其他文件操作结合使用

os.truncate 可以与其他文件操作结合使用,以实现更复杂的工作流程。此示例显示了与文件读取的集成。

combined_operations.py
import os

file_path = "data.bin"

# Create binary file with some data
with open(file_path, "wb") as f:
    f.write(b"\x01\x02\x03\x04\x05\x06\x07\x08")

# Truncate to remove last 4 bytes
os.truncate(file_path, 4)

# Read remaining content
with open(file_path, "rb") as f:
    content = f.read()
    print(f"Remaining bytes: {content}")
    print(f"Size after truncate: {len(content)} bytes")

# Extend file and verify
os.truncate(file_path, 8)
with open(file_path, "rb") as f:
    content = f.read()
    print(f"Extended bytes: {content}")
    print(f"Size after extension: {len(content)} bytes")

这将创建一个二进制文件,将其截断,然后在验证每一步的内容的同时对其进行扩展。在扩展期间添加的空字节是可见的。

使用非文本数据或检查扩展期间添加的实际字节时,二进制模式至关重要。

性能注意事项

此示例将 os.truncate 与文件大小修改的替代方法进行基准测试,以演示性能特征。

performance_test.py
import os
import timeit

file_path = "large_file.bin"
size_mb = 10  # 10MB file
test_size = 5  # Truncate to 5MB

def create_large_file():
    with open(file_path, "wb") as f:
        f.seek(size_mb * 1024 * 1024 - 1)
        f.write(b"\0")

def method_truncate():
    os.truncate(file_path, test_size * 1024 * 1024)

def method_write():
    with open(file_path, "r+") as f:
        f.truncate(test_size * 1024 * 1024)

# Setup
create_large_file()

# Benchmark
truncate_time = timeit.timeit(method_truncate, number=100)
write_time = timeit.timeit(method_write, number=100)

print(f"os.truncate average: {truncate_time/100:.6f}s")
print(f"file.truncate average: {write_time/100:.6f}s")

# Cleanup
os.remove(file_path)

这将创建一个大文件,然后比较截断方法。 os.truncate 通常更快,因为它在文件系统级别运行。

文件越大,截断操作越频繁,性能差异就越明显。

安全注意事项

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我在编程教学方面拥有超过十年的经验。

列出所有 Python 教程