2009-04-11 17 views

risposta

28

Direi che è possibile, giocando con TarInfo e TarFile.addfile passando un StringIO come un oggetto file.

Molto grezzo, ma funziona

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

Si può semplicemente pronunciare StringIO.StringIO ("ciao") per sostituire la scrittura e la ricerca. – misha

+0

è la procedura simile agli oggetti python3 e bytesIO? – proteneer

+2

@proteneer: Credo in python 3 il metodo seek fornisce una lunghezza binaria, mentre internamente usa la funzione '' 'len()' '', in modo che la funzione '' 'tarfile.copyfileobj''' fallisca con '' 'solleva OSError (" fine del file raggiunto ")' '' – luckydonald

14

Come Stefano ha sottolineato, è possibile utilizzare TarFile.addfile e 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() 

probabilmente si vorrà per riempire altri campi di tarinfo (ad esempio mtime, uname ecc) così.

+0

è il "Come Stefano ha sottolineato" una modifica? Altrimenti, non vedo cosa stai facendo in modo diverso. Grazie per la risposta lo stesso. – gatoatigrado

+0

Penso che Stefano non abbia pubblicato alcun codice nel momento in cui ho scritto la mia risposta, ha solo notato che TarFile.addfile e StringIO possono essere usati. La mia memoria è poco sfocata, però. – avakar

+0

FWIW, sì, le informazioni dettagliate di @ Stefano sono state aggiunte in [un edit] (http://stackoverflow.com/posts/740839/revisions) dopo averlo scritto. Anche l'altra risposta che diceva la stessa cosa avveniva quasi simultaneamente. – mattdm

2

è necessario utilizzare gli oggetti TarInfo e il metodo addfile invece del solito metodo 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)) 
2

Nel mio caso ho voluto leggere da un file tar esistente, aggiungere alcuni dati ai contenuti, e scrivere in un nuovo file. Qualcosa di simile:

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) 

Codice aggiuntivo è necessario per la gestione di directory e collegamenti.

2

Solo per la cronologia:
Gli oggetti StringIO hanno una proprietà .len.
Non c'è bisogno di cercare (0) e fare len (foo.buf)
Non c'è bisogno di tenere l'intera stringa in giro per fare len(), o Dio non voglia, fare la contabilità da soli.

(Forse non ha al momento il PO è stato scritto.)

6

ho trovato questo guardando come servire in Django un appena creato in memoria .tgz archivio, può essere qualcun altro troverà il mio codice utile:

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