You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python向tar/tar.gz添加文件后出现空文件问题求助

问题原因与解决方案

我之前也踩过这个坑!你遇到的问题核心在于手动创建的TarInfo对象缺少关键的size属性——tarfile模块完全不知道要从你的文件流里读取多少字节,所以默认只取了0字节,导致归档里的文件是空的。这个问题和gzip压缩无关,所以去掉:gz用普通tar文件也会出现同样的情况。

解决方案1:用gettarinfo()自动生成正确的TarInfo

如果你是操作本地文件,最简单的方式是用tarfile.TarFile.gettarinfo()方法自动获取文件的元信息(包括大小),这样就不用手动设置size了:

import tarfile

# 创建测试文件
with open("testfile.txt", "w") as f:
    f.write("TESTTESTTEST")

# 创建归档文件
with tarfile.open("archfile.tar.gz", "x:gz") as archive:
    with open("testfile.txt", 'rb') as f:
        # 自动获取文件的TarInfo,指定归档内的文件名
        tar_info = archive.gettarinfo(fileobj=f, arcname="testfile.txt")
        # 注意:gettarinfo会将文件指针移到末尾,所以要重置到开头
        f.seek(0)
        archive.addfile(tar_info, f)

# 验证读取
with tarfile.open("archfile.tar.gz", "r:gz") as archive:
    print(archive.extractfile("testfile.txt").read())  # 输出 b'TESTTESTTEST'

或者更简单,直接用archive.add()方法一步到位:

with tarfile.open("archfile.tar.gz", "x:gz") as archive:
    archive.add("testfile.txt", arcname="testfile.txt")

解决方案2:手动设置TarInfo.size属性

如果你必须手动创建TarInfo(比如操作内存中的流),一定要记得设置size为流的实际字节长度:

针对本地文件

import tarfile
import os

# 创建测试文件
with open("testfile.txt", "w") as f:
    f.write("TESTTESTTEST")

# 获取文件大小
file_size = os.path.getsize("testfile.txt")

with tarfile.open("archfile.tar.gz", "x:gz") as archive:
    tar_info = tarfile.TarInfo("testfile.txt")
    tar_info.size = file_size  # 关键:设置正确的文件大小
    with open("testfile.txt", 'rb') as f:
        archive.addfile(tar_info, f)

# 验证读取
with tarfile.open("archfile.tar.gz", "r:gz") as archive:
    print(archive.extractfile("testfile.txt").read())

针对内存中的字符串(你的最终目标)

注意:tarfile需要二进制流,所以要把字符串转成bytes,用io.BytesIO而不是io.StringIO:

import tarfile
import io

# 内存中的二进制内容
content = b"TESTTESTTEST"
# 或者从字符串转:content = "TESTTESTTEST".encode('utf-8')
stream = io.BytesIO(content)

with tarfile.open("archfile.tar.gz", "x:gz") as archive:
    tar_info = tarfile.TarInfo("testfile.txt")
    tar_info.size = len(content)  # 设置流的实际字节长度
    stream.seek(0)  # 确保流的指针在开头
    archive.addfile(tar_info, stream)

# 验证读取
with tarfile.open("archfile.tar.gz", "r:gz") as archive:
    print(archive.extractfile("testfile.txt").read())  # 输出 b'TESTTESTTEST'

总结

不管是本地文件还是内存流,只要你手动创建TarInfo对象,就必须指定正确的size属性——tarfile模块不会自动检测流的长度,只会按照TarInfo.size的值去读取字节。用gettarinfo()方法可以自动处理这些元信息,是更稳妥的选择。

内容的提问来源于stack exchange,提问作者dilaudid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:31:07