最常见的io操作是将磁盘中的文件读到内存以及内存内容写入文I件。还有一种内存和内存之间的IO,叫类文件对象,python中的StringIO
和BytesIO
就是类文件对象,通俗解释即:像操作文件一样在内存中操作字符串和二进制内容
磁盘上的文件,就是将数据持久化到磁盘的一块区域,供后面重复使用。其优点就是持久化稳定不丢失,但是缺点也很明显,就是每次要使用都要从磁盘读入,相对内存而言很缓慢。如果只是短时间的重复利用,并不希望长期持久化,而且对速度的要求比较高,这时候就可以考虑缓存。
这种类文件对象是用来存储字符串的,下面展示了如何使用
from io import StringIO, BytesIO
if __name__ == "__main__":
# 初始化并写入内容
# io_obj = StringIO("i love china")
# 初始化io
io_obj = StringIO()
# 写入内容
io_obj.write("i love china")
# 读取io中内容
content = io_obj.read()
# 返回:空
print(content)
如上打印结果为空,这是因为内存中的对象有一个标志位的概念,往里面写入,标志位后移到下一个空白处。而读数据的时候是从标志位开始读,所以想要读取前面的数据需要手动将标志位进行移动。
如下,通过seek方法将标志位移动到到首位,再读取内容就会读出所有内容;将seek中的0换成2会发现会舍弃前面两个字符。
io_obj = StringIO()
# 写入内容
io_obj.write("i love china")
# 将标志位移动到首位
io_obj.seek(0)
# 读取io中内容
content = io_obj.read()
# 返回:i love china
print(content)
通过getvalue()
方法获取全部内容,该方法不受标志位影响。注意,当我们在初始化io时同时写入内容io_obj = StringIO("i love china")
,此时读取内容也不受标志位影响
io_obj = StringIO()
# 写入内容
io_obj.write("i love china")
# 读取io中内容
content = io_obj.getvalue()
# 返回:i love china
print(content)
readline()
方法读取以\n
为界的一行数据,readlines()
读取所有行,注意标志位置零
io_obj = StringIO()
# 写入内容
io_obj.write("i love china\n wo ai zhongguo")
# 读取io中内容
io_obj.seek(0)
# content = io_obj.readline()
# 返回:i love china
# print(content)
content_all = io_obj.readlines()
# 返回所有行:['i love china\n', ' wo ai zhongguo']
print(content_all)
该对象使用完毕直接关掉,该内存里的内容被清空
io_obj.close()
StringIO只能存储字符串,对于图片视频等Bytes类型的内容就需要用到专门存储Bytes类型的BytesIO对象,用法完全相同,即:write()
写内容,read()
读内容,getvalue()
获取所有内容…
# 初始化io
io_obj = BytesIO()
io_obj.write("i love china".encode("utf-8"))
io_obj.seek(0)
content = io_obj.read()
# 返回:b'i love china'
print(content)
下面展示直接从网络读取一张图片,而不需要将图片保存到本地,再读本地文件
import requests
from PIL import Image
response = requests.get('https://ts1.cn.mm.bing.net/th/id/R-C.fd4056c8c00979ab8561f8db8219c2ae?rik=JPk67EIYaKIS3A&riu=http%3a%2f%2fimg.mm4000.com%2ffile%2fa%2fa2%2f869bd2bd6a.jpg&ehk=2z%2bPuRHJOYtkm9ICs8fPs0EJbE96jJX2E8QyrVP5kyQ%3d&risl=&pid=ImgRaw&r=0')
img = BytesIO()
img.write(response.content)
pict = Image.open(img)
pict.show()
img.close()
返回结果
注意:此处我们无法直接把下载的Bytes类型用Image打开,Image接受的参数是一个文件对象,或者类文件对象。所以要么是磁盘上的文件,要么是内存中的BytesIO