文字列をtarfileに直接書き込む方法はありますか? http://docs.python.org/library/tarfile.html から、ファイルシステムにすでに書き込まれているファイルのみを追加できるようです。
StringIOをファイルオブジェクトとして渡すTarInfoe TarFile.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()
Stefanoが指摘したように、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
の他のフィールド(例:mtime
、uname
など)にも入力することをお勧めします。
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
記録のために:
StringIOオブジェクトには.lenプロパティがあります。
seek(0)してlen(foo.buf)を実行する必要はありません
[。
(たぶん、OPが書かれた時点ではそうではありませんでした。)
Python 3のソリューションは_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))
_
書き込み可能なstringバッファーが本当に必要な場合は、@ StefanoBoriniが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)
_
私の場合、既存の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)
ディレクトリとリンクを処理するには、追加のコードが必要です。
通常の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))