Python3 IO编程之StringIO和BytesIO
StringIO
很多时候,数据读写不一定是文件,也可以在内存中读写。
要把str写入StringIO,我们需要先创建一个StringIO,然后像文件一样写入即可
>>> from io import StringIO >>> f=StringIO() >>> f.write('hello') 5 >>> f.write(' ') 1 >>> f.write('world!') 6 >>> f <_io.StringIO object at 0x7f6bbc76e318> >>> f.getvalue() 'hello world!'
getvalue()方法用于获得写入后的str
要读取StringIO,可以用一个str初始化StringIO,然后像读文件一样读取
>>> f=StringIO('Hello!\nHi!\nGoodbye!') >>> while True: ... s=f.readline() ... if s=='': ... break ... print(s.strip()) ... Hello! Hi! Goodbye!
BytesIO
StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。
BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes:
>>> from io import BytesIO >>> f=BytesIO() >>> f.write('中文'.encode('utf-8')) 6 >>> f.getvalue() b'\xe4\xb8\xad\xe6\x96\x87'
请注意,写入的不是str,而是经过UTF-8编码的bytes。
和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取:
>>> from io import BytesIO >>> f=BytesIO(b'\xe4\xb8\xad\xe6\x96\x87') >>> f.read() b'\xe4\xb8\xad\xe6\x96\x87'
StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口。
用一个列子加深对StringIO和BytesIO的理解
# StringIO和BytesIO # stringIO 比如说,这时候,你需要对获取到的数据进行操作,但是你并不想把数据写到本地硬盘上,这时候你就可以用stringIO from io import StringIO from io import BytesIO def outputstring(): return 'string \nfrom \noutputstring \nfunction' s = outputstring() #s为字符串'string \nfrom \noutputstring \nfunction' #将函数返回的数据在内存中读 sio=StringIO(s) #可以用StringIO本身的方法 sio.getvalue() #输出 #'string \nfrom \noutputstring \nfunction' #也可以用file-like object的方法 s=sio.readlines() #readlines返回的是一个列表 #['string \n', 'from \n', 'outputstring \n', 'function'] for i in s: print(i.strip()) #去除尾部的回车符号输出 #string #from #outputstring #function #将函数返回的数据在内存中写 s=outputstring() sio=StringIO() sio.write(s) #如果是在终端会显示指针位置值36 #可以用StringIO本身的方法查看 print(sio.getvalue()) #如果你用file-like object的方法查看的时候,你会发现数据为空 #因为指针位置在尾部36 for i in sio.readlines(): print(i.strip()) #这时候我们需要修改下文件的指针位置 #就可以打印内容了 sio.seek(0,0) #打印指针位置 print(sio.tell()) #结果为0 # 这就涉及到了两个方法seek 和 tell # tell 方法获取当前文件读取指针的位置 # seek 方法,用于移动文件读写指针到指定位置,有两个参数,第一个offset: 偏移量,需要向前或向后的字节数,正为向后,负为向前;第二个whence: 可选值,默认为0,表示文件开头,1表示相对于当前的位置,2表示文件末尾 # 用seek方法时,需注意,如果你打开的文件没有用'b'的方式打开,则offset无法使用负值哦 #在使用file-like object方法可以打印了 for i in sio.readlines(): print(i.strip()) # stringIO 只能操作str,如果要操作二进制数据,就需要用到BytesIO # 上面的sio无法用seek从当前位置向前移动,这时候,我们用'b'的方式写入数据,就可以向前移动了 bio=BytesIO() bio.write(s.encode('utf-8')) #使用getvalue()方法quzhi print(bio.getvalue()) #b'string \nfrom \noutputstring \nfunction' #修改指针 #1代表从当前位置,-36代表往前移动36 bio.seek(-36,1) bio.tell() #0 for i in bio.readlines(): print(i.strip())
注意:当使用StringIO去初始化的时候,其指针是指向0的位置,而如果是用write的方法的时候,其指针会移动到最后
举例如下
>>> sio=StringIO('abc') >>> sio.getvalue() 'abc' >>> sio.tell() 0 #初始化指针指向0 值为'abc' >>> sio=StringIO('def') >>> sio.tell() 0 >>> sio.getvalue() 'def' #再次初始化会覆盖原值
对比write方法
>>> a=StringIO() #写指针加3 >>> a.write('123') 3 #再次写追加指针再加3 >>> a.write('456') 3 #值为追加非覆盖 >>> a.getvalue() '123456' #最后指针为6 >>> a.tell() 6