python - python - 将io.StringIO转换为io.BytesIO

67 4

原始问题:我得到 StringIO对象,如何将它转换为 BytesIO

更新:更一般的问题是,如何将二进制(已编码)文件对象转换成像python3中的对象那样的解码文件。

我得到的朴素方法是:

 

import io


sio = io.StringIO('wello horld')


bio = io.BytesIO(sio.read().encode('utf8'))


print(bio.read()) # prints b'wello horld'



有更优雅的方式吗?

时间: 原作者:

51 2

它可能是一个将字符流转换为字节流的通用工具,所以,这里是,

 

import io



class EncodeIO(io.BufferedIOBase):


 def __init__(self,s,e='utf-8'):


 self.stream=s # not raw, since it isn't


 self.encoding=e


 self.buf=b" " # encoded but not yet returned


 def _read(self,s): return self.stream.read(s).encode(self.encoding)


 def read(self,size=-1):


 b=self.buf


 self.buf=b" " 


 if size is None or size<0: return b+self._read(None)


 ret=[]


 while True:


 n=len(b)


 if size<n:


 b,self.buf=b[:size],b[size:]


 n=size


 ret.append(b)


 size-=n


 if not size: return b" " .join(ret)


 b=self._read(min((size+1024)//2,size))


 read1=read



显然,write可以对称地解码输入,并将它发送到底层流,但是,只需处理字符的一部分。

原作者:
64 5

就像一些指出的,你需要自己做编码/解码。

但是,你可以用一种优雅的方式实现你自己的TextIOWrapper

以下是一个示例:

 

class BytesIOWrapper:


 def __init__(self, string_buffer, encoding='utf-8'):


 self.string_buffer = string_buffer


 self.encoding = encoding



 def __getattr__(self, attr):


 return getattr(self.string_buffer, attr)



 def read(self, size=-1):


 content = self.string_buffer.read(size)


 return content.encode(self.encoding)



 def write(self, b):


 content = b.decode(self.encoding)


 return self.string_buffer.write(content)



产生这样的输出:

 

In [36]: bw = BytesIOWrapper(StringIO(" some lengt˙˚hyÔstring in here" ))



In [37]: bw.read(15)


Out[37]: b'some lengtxcbx99xcbx9ahyxc3x94'



In [38]: bw.tell()


Out[38]: 15



In [39]: bw.write(b'ME')


Out[39]: 2



In [40]: bw.seek(15)


Out[40]: 15



In [41]: bw.read()


Out[41]: b'MEring in here'



原作者:
68 2

@foobarna回答可以通过继承一些io基类来改进,

 

import io


sio = io.StringIO('wello horld')



class BytesIOWrapper(io.BufferedReader):


" "" Wrap a buffered bytes stream over TextIOBase string stream." "" 



 def __init__(self, text_io_buffer, encoding=None, errors=None, **kwargs):


 super(BytesIOWrapper, self).__init__(text_io_buffer, **kwargs)


 self.encoding = encoding or text_io_buffer.encoding or 'utf-8'


 self.errors = errors or text_io_buffer.errors or 'strict'



 def _encoding_call(self, method_name, *args, **kwargs):


 raw_method = getattr(self.raw, method_name)


 val = raw_method(*args, **kwargs)


 return val.encode(self.encoding, errors=self.errors)



 def read(self, size=-1):


 return self._encoding_call('read', size)



 def read1(self, size=-1):


 return self._encoding_call('read1', size)



 def peek(self, size=-1):


 return self._encoding_call('peek', size)



bio = BytesIOWrapper(sio)


print(bio.read()) # b'wello horld'



原作者:
96 5

有趣的是,尽管这个问题看起来合理,但是,并不容易找出我需要将StringIO转换为BytesIO的原因,这两者基本上是缓冲区,你通常只需要其中一个使用字节或文本进行额外操作。

我可能是错误的,但是,我认为你的问题实际上是如何使用一个BytesIO实例。

在这种情况下,它是一个常见的问题,解决方案是 codecs模块。

使用它的两种常见情况如下:

编写要读取的文件对象

 

In [16]: import codecs, io



In [17]: bio = io.BytesIO(b'qwenasdn')



In [18]: StreamReader = codecs.getreader('utf-8') # here you pass the encoding



In [19]: wrapper_file = StreamReader(bio)



In [20]: print(repr(wrapper_file.readline()))


'qwen'



In [21]: print(repr(wrapper_file.read()))


'asdn'



In [26]: bio.seek(0)


Out[26]: 0



In [27]: for line in wrapper_file:


 . ..: print(repr(line))


 . ..:


'qwen'


'asdn'



编写要写入的文件对象

 

In [28]: bio = io.BytesIO()



In [29]: StreamWriter = codecs.getwriter('utf-8') # here you pass the encoding



In [30]: wrapper_file = StreamWriter(bio)



In [31]: print('жаба', 'цап', file=wrapper_file)



In [32]: bio.getvalue()


Out[32]: b'xd0xb6xd0xb0xd0xb1xd0xb0 xd1x86xd0xb0xd0xbfn'



In [33]: repr(bio.getvalue().decode('utf-8'))


Out[33]:" 'жаба цапn'" 



原作者:
67 5

来自你的示例的bio_io.BytesIO类对象,你使用了read()函数的2倍。

我提出了bytes转换和一个read()方法:

 

sio = io.StringIO('wello horld')


b = bytes(sio.read(), encoding='utf-8')


print(b)



但是第二个变量应该更快:

 

sio = io.StringIO('wello horld')


b = sio.read().encode()


print(b)



原作者:
...