39

文字列をtarfileに直接書き込む方法はありますか?http://docs.python.org/library/tarfile.htmlから、ファイルシステムにすでに書き込まれているファイルのみを追加できるようです。

4

7 に答える 7

37

StringIOをファイルオブジェクトとして渡すTarInfoeTarFile.addfileで遊ぶことで、それは可能だと思います。

非常にラフですが、機能します

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()
于 2009-04-11T21:48:26.313 に答える
16

ステファノが指摘したように、あなたはとを使うことができTarFile.addfileます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()

おそらく、他のフィールドtarinfo(たとえばmtimeunameなど)にも入力することをお勧めします。

于 2009-04-11T22:02:46.903 に答える
11

これは、メモリ.tgzアーカイブに作成されたばかりのDjangoで提供する方法を探しているので、他の誰かが私のコードを役立つと思うかもしれません。

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
于 2016-11-03T00:37:03.837 に答える
6

Python3のソリューションはを使用しio.BytesIOます。TarInfo.size文字列の長さではなく、必ずバイトの長さに設定してください。

単一の文字列が与えられた場合、最も簡単な解決策は、それを呼び出し.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))

@Stefano Borini for 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)
于 2018-10-09T15:26:25.107 に答える
4

念のために
言っておきますが、StringIOオブジェクトには.lenプロパティがあります。
seek(0)を実行してlen(foo.buf)を実行
する必要はありません。len()を実行するために文字列全体を保持する必要はありません。

(たぶん、OPが書かれた時点ではそうではありませんでした。)

于 2014-08-06T10:12:30.507 に答える
3

私の場合、既存の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)

ディレクトリとリンクを処理するには、追加のコードが必要です。

于 2013-08-03T10:21:11.760 に答える
2

通常のaddメソッドの代わりに、TarInfoオブジェクトとaddfileメソッドを使用する必要があります。

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))
于 2009-04-11T22:04:37.007 に答える