python python将字符串直接写入tarfile

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/740820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:47:04  来源:igfitidea点击:

python write string directly to tarfile

pythonfilefile-iotar

提问by gatoatigrado

Is there a way to write a string directly to a tarfile? From http://docs.python.org/library/tarfile.htmlit looks like only files already written to the file system can be added.

有没有办法将字符串直接写入 tarfile?从http://docs.python.org/library/tarfile.html看来,只能添加已经写入文件系统的文件。

采纳答案by Stefano Borini

I would say it's possible, by playing with TarInfo e TarFile.addfile passing a StringIO as a fileobject.

我会说这是可能的,通过使用 TarInfo e TarFile.addfile 将 StringIO 作为文件对象传递。

Very rough, but works

非常粗糙,但有效

import tarfile
import StringIO

tar = tarfile.TarFile("test.tar","w")

string = StringIO.StringIO()
string.write("hello")
string.seek(0)
info = tarfile.TarInfo(name="foo")
info.size=len(string.buf)
tar.addfile(tarinfo=info, fileobj=string)

tar.close()

回答by avakar

As Stefano pointed out, you can use TarFile.addfileand StringIO.

正如 Stefano 指出的那样,您可以使用TarFile.addfileand StringIO

import tarfile, StringIO

data = 'hello, world!'

tarinfo = tarfile.TarInfo('test.txt')
tarinfo.size = len(data)

tar = tarfile.open('test.tar', 'a')
tar.addfile(tarinfo, StringIO.StringIO(data))
tar.close()

You'll probably want to fill other fields of tarinfo(e.g. mtime, unameetc.) as well.

您可能还想填写tarinfo(例如mtimeuname等)的其他字段。

回答by scythargon

I found this looking how to serve in Django a just created in memory .tgz archive, may be somebody else will find my code usefull:

我发现这看起来如何在 Django 中提供一个刚刚在内存中创建的 .tgz 存档,可能其他人会发现我的代码有用:

import tarfile
from io import BytesIO


def serve_file(request):
    out = BytesIO()
    tar = tarfile.open(mode = "w:gz", fileobj = out)
    data = 'lala'.encode('utf-8')
    file = BytesIO(data)
    info = tarfile.TarInfo(name="1.txt")
    info.size = len(data)
    tar.addfile(tarinfo=info, fileobj=file)
    tar.close()

    response = HttpResponse(out.getvalue(), content_type='application/tgz')
    response['Content-Disposition'] = 'attachment; filename=myfile.tgz'
    return response

回答by Todd Owen

The solution in Python 3 uses io.BytesIO. Be sure to set TarInfo.sizeto the length of the bytes, not the length of the string.

Python 3 中的解决方案使用io.BytesIO. 一定要设置TarInfo.size为字节的长度,而不是字符串的长度。

Given a single string, the simplest solution is to call .encode()on it to obtain bytes. In this day and age you probably want UTF-8, but if the recipient is expecting a specific encoding, such as ASCII (i.e. no multi-byte characters), then use that instead.

给定一个字符串,最简单的解决方案是调用.encode()它来获取字节。在当今时代,您可能需要 UTF-8,但如果接收者希望使用特定的编码,例如 ASCII(即没有多字节字符),那么请改用它。

import io
import tarfile

data = 'hello\n'.encode('utf8')
info = tarfile.TarInfo(name='foo.txt')
info.size = len(data)

with tarfile.TarFile('test.tar', 'w') as tar:
    tar.addfile(info, io.BytesIO(data))

If you really need a writable stringbuffer, similar to the accepted answer by @Stefano Borini for Python 2, then the solution is to use io.TextIOWrapperover an underlying io.BytesIObuffer.

如果您确实需要一个可写的字符串缓冲区,类似于 @Stefano Borini 为 Python 2 接受的答案,那么解决方案是使用io.TextIOWrapper底层io.BytesIO缓冲区。

import io
import tarfile

textIO = io.TextIOWrapper(io.BytesIO(), encoding='utf8')
textIO.write('hello\n')
bytesIO = textIO.detach()
info = tarfile.TarInfo(name='foo.txt')
info.size = bytesIO.tell()

with tarfile.TarFile('test.tar', 'w') as tar:
    bytesIO.seek(0)
    tar.addfile(info, bytesIO)

回答by Alias_Knagg

Just for the record:
StringIO objects have a .len property.
No need to seek(0) and do len(foo.buf)
No need to keep the entire string around to do len() on, or God forbid, do the accounting yourself.

只是为了记录:
StringIO 对象有一个 .len 属性。
不需要seek(0) 和做len(foo.buf)
不需要保留整个字符串来执行len(),或者上帝保佑,自己做会计。

( Maybe it did not at the time the OP was written. )

(也许在编写 OP 时还没有。)

回答by Eli Courtwright

You have to use TarInfo objects and the addfile method instead of the usual add method:

您必须使用 TarInfo 对象和 addfile 方法而不是通常的 add 方法:

from StringIO import StringIO
from tarfile import open, TarInfo

s = "Hello World!"
ti = TarInfo("test.txt")
ti.size = len(s)

tf = open("testtar.tar", "w")
tf.addfile(ti, StringIO(s))

回答by z0r

In my case I wanted to read from an existing tar file, append some data to the contents, and write it to a new file. Something like:

就我而言,我想从现有的 tar 文件中读取数据,将一些数据附加到内容中,然后将其写入一个新文件。就像是:

for ti in tar_in:
    buf_in = tar.extractfile(ti)
    buf_out = io.BytesIO()
    size = buf_out.write(buf_in.read())
    size += buf_out.write(other data)
    buf_out.seek(0)
    ti.size = size
    tar_out.addfile(ti, fileobj=buf_out)

Extra code is needed for handling directories and links.

处理目录和链接需要额外的代码。