Buffer binário em Python
Pergunta
Em Python você pode usar StringIO para um buffer semelhante a um arquivo para dados de caracteres. Arquivo mapeado em memória basicamente faz algo semelhante para dados binários, mas requer um arquivo que é usado como base.O Python possui um objeto de arquivo destinado a dados binários e é apenas memória, equivalente ao Java? ByteArrayOutputStream?
O caso de uso que tenho é que desejo criar um arquivo ZIP na memória e Arquivo Zip requer um objeto semelhante a um arquivo.
Solução
Você provavelmente está procurando io.BytesIO aula.Funciona exatamente como StringIO, exceto que suporta dados binários:
from io import BytesIO
bio = BytesIO(b"some initial binary data: \x00\x01")
StringIO lançará TypeError:
from io import StringIO
sio = StringIO(b"some initial binary data: \x00\x01")
Outras dicas
Contanto que você não tente colocar nenhum dado Unicode em seu StringIO
e você tem cuidado para NÃO usar cStringIO
você deveria estar bem.
De acordo com StringIO documentação, contanto que você mantenha unicode ou 8 bits, tudo funciona conforme o esperado.Presumivelmente, StringIO
faz algo especial quando alguém faz um f.write(u"asdf")
(o que o ZipFile não faz, que eu saiba).De qualquer forma;
import zipfile
import StringIO
s = StringIO.StringIO()
z = zipfile.ZipFile(s, "w")
z.write("test.txt")
z.close()
f = file("x.zip", "w")
f.write(s.getvalue())
s.close()
f.close()
funciona exatamente como esperado e não há diferença entre o arquivo no arquivo resultante e o arquivo original.
Se você conhece um caso específico em que essa abordagem não funciona, eu ficaria muito interessado em saber mais sobre isso :)
Veja o pacote struct: https://docs.python.org/library/struct.html, permite interpretar strings como dados binários compactados.
Não tenho certeza se isso responderá completamente à sua pergunta, mas você pode usar struct.unpack() para converter dados binários em objetos python.
import struct
f = open(filename, "rb")
s = f.read(8)
x, y = struct.unpack(">hl", s)
Neste exemplo, o ">" diz para ler big-endian, o "h" lê um comprimento de 2 bytes e o "l" é para um comprimento de 4 bytes.obviamente você pode alterá-los para o que precisar ler dos dados binários ...