سؤال

هل هناك طريقة لكتابة سلسلة مباشرة إلى tarfile؟ من http://docs.python.org/library/tarfile.html. يبدو أن الملفات فقط مكتوبة بالفعل إلى نظام الملفات يمكن إضافتها.

هل كانت مفيدة؟

المحلول

أود أن أقول أنه من الممكن، من خلال اللعب مع Tarinfo e Tarfile.Addfile تمر Stringio كعلفي.

خشنة جدا، ولكن يعمل

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()

نصائح أخرى

كما أشار ستيفانو، يمكنك استخدام 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.
لا حاجة للبحث (0) و do len (foo.buf)
لا حاجة للحفاظ على السلسلة بأكملها إلى فعل لين () أو لا سمح الله، هل يحقئ نفسك.

(ربما لم يحدث في وقت كتابة المرجع.)

يجب عليك استخدام كائنات 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))

في حالتي، أردت أن أقرأ من ملف قارف موجود، إلحاق بعض البيانات إلى المحتويات، واكتبها إلى ملف جديد. شيء مثل:

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)

هناك حاجة إلى رمز إضافي لمعالجة الدلائل والروابط.

الحل في 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))

إذا كنت حقا بحاجة قابلة للكتابة سلسلة المخزن المؤقت، مشابه للإجابة المقبولة من 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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top