最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • Python内存操作的文件对象 StringIo 和 BytesIO

    大家还记的文件对象的定义吗,我们知道像 open 函数返回的这种有个 read 函数的对象,在 Python
    中统称为文件对象。文件对象不一定是必须要和磁盘,网卡这种外部设备打交道,和内存打交道的具有
    read 和 write 函数的对象,我们也叫文件对象。

    对磁盘的读写操作速度没有直接对内存操作快,很多时候,数据读写不一定是文件,也可以在内存中读写,本节我们就来学习对内存操作的文件对象 StringIo 和 BytesIO。

    StringIO

    要把字符串写入 StringIO,我们需要先创建一个 StringIO 对象,然后调用 StringIO 对象的 write
    函数写入字符串(字符串必须为 unicode 类型),然后我们可以通过 StringIO 对象的 getvalue 函数读取字符串,注意使用完后不要忘记调用文件对象的 close 函数。

    from io import StringIO
    
    f = StringIO()
    f.write("hello")
    print(f.getvalue())
    f.close()  # 不要忘记调用文件对象的 close 函数

    我们也可以在创建 StringIO 对象的时候写入字符串。

    from io import StringIO
    
    f = StringIO(u"hello")  # 调用 StringIO 的构造函数写入字符串
    print(f.getvalue())
    f.close()

    我们也可以使用文件对象的 read 函数读取字符串,但要注意调用 write 函数 和 read 函数会导致把指针指向字符串的末尾。

    from io import StringIO
    
    f = StringIO()
    f.write("hello")
    print(f.read())  # 从字符串末尾开始读,所以没有内容
    f.close()        # 不要忘记调用文件对象的 close 函数

    我们可以使用 seek 函数把指针定位到开始,然后调用 read 函数读取,或者直接使用 getvalue 函数读取(总是从字符串开始位置读取)。

    from io import StringIO
    
    f = StringIO()
    f.write("hello")
    f.seek(0)            # 指针重新定位到字符串开始
    print(f.read())      # 读完后指针又定位到字符串末尾
    f.seek(0)            # 指针重新定位到字符串开始
    print(f.read())      # 读完后指针又定位到字符串末尾
    print(f.getvalue())  # getvalue 函数总是从字符串开始位置开始读
    f.close()            # 不要忘记调用文件对象的 close 函数

    用 StringIO 模块进行读写操作和我们自己定义对象读写字符串实质上是一样的,只是
    StringIO 模块里面有类似文件对象提供的函数,更方便于我们对字符串进行操作,同理我们可以自己定义一个类来实现一个简易型的 myStringIO。

    class myStringIO():
        def __init__(self, data):
            self.data = data
    
        def read(self):
            return self.data
    
        def write(self, data):
            self.data = data
    
        def getvalue(self):
            return self.data
    
        def close(self):
            del self.data
    
    f = myStringIO(u"hello")
    print(f.getvalue())
    f.close()

    BytesIO

    StringIO 操作的只能是字符串,如果要操作二进制数据(视频,图片,音频等等非字符流数据),就需要使用
    BytesIO,下面我们使用 BytesIO 进行读写图片。注意,BytesIO 接收的参数和返回的结果都是字节类型。

    from io import BytesIO
    fother = open("d:/test.png", "rb")  # 确保 d 盘下有 test.png 文件
    data = fother.read()
    fother.close()
    
    f = BytesIO(data)    # data 是字节类型
    print(f.getvalue())  # 结果为字节类型
    f.close()

    为了弄明白 BytesIO 使用的场景,我们从一个例子说起。我们写个程序:从网络上下载二进制数据(视频,图片,音频等等非字符流数据),然后存储在磁盘中。

    from io import BytesIO
    from urllib import request  # 网络库
    
    rst = request.urlopen("http://birdpython.com/static/img/logo.png")  # 下载图片
    f = BytesIO(rst.read())  # 把图片二进制文件放入 BytesIO 对象中
    
    fdisk = open("d:/xx.png", "wb")
    fdisk.write(f.getvalue())
    fdisk.close()
    
    f.close()

    同学们可能会想,我们也可以直接把网上下载的二进制数据存到磁盘中啊,为什么还要用 BytesIO
    对象存储起来,这不是多此一举吗!如下代码。

    from urllib import request  # 网络库
    import ssl
    
    context = ssl._create_unverified_context()
    rst = request.urlopen("http://birdpython.com/static/img/logo.png", context=context)  # 下载图片
    data = rst.read()
    
    fdisk = open("d:/xx.png", "wb")
    fdisk.write(data)
    fdisk.close()

    当然,如果只是这种简单的需求,我们完全不需要使用 BytesIO,那么,现在我们增加一项需求,要求把下载的图片大小处理成 64 像素高和 64
    像素宽,然后再存储起来。这个时候,我们可以使用专业的图片处理模块 PIL 提供的函数来修改图片大小,然而
    PIL 模块需要传入一个文件对象或者类文件对象(不能直接传入字节类型变量)来操作,这时候我们可以传入一个存储该二进制图片数据的
    BytesIO 对象给 PIL 对象。

    from io import BytesIO
    from urllib import request  # 网络库
    from PIL import Image       # 第三方图形处理模块(安装命令:pip install pillow)
    import ssl
    
    context = ssl._create_unverified_context()
    rst = request.urlopen("http://birdpython.com/static/img/logo.png", context=context)  # 下载图片
    data = rst.read()
    
    f = BytesIO(data)              # 把图片二进制文件放入 BytesIO 对象中
    img = Image.open(f)            # 需要传入一个文件对象
    newimg = img.resize((64, 64))  # 修改图片像素大小为 64 x 64
    newimg.save("d:/xx.png")       # 存储处理后的图片
    f.close()

    如果你是个杠精,你说你可以不用这些专业的图形处理模块来完成需求,比如自己去写业务逻辑来改变图片大小,那如果有更复杂的图片处理需求呢?我可以告诉你,这几乎是不可能的事情!

    内存 IO(StringIO 和 BytesIO)和文件 IO 的主要区别

    内存 IO 和文件 IO 的本质区别就在于文件 IO 是程序通过操作系统操作磁盘文件,而内存 IO 是我们直接用程序操作内存。

    如果我们想要存储的内容持久化就只能使用文件 IO,因为内存 IO 是对内存进行操作,在我们进程结束后,内存就被操作系统回收了。

    文件 IO 有读写标识符,内存 IO 没有读写标识符,大家想想这是不是理所当然的。

    本节重要知识点

    会使用 StringIO 文件对象。

    会使用 BytesIO 文件对象。

    知道 StringIO 和 BytesIO 的区别。

    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » Python内存操作的文件对象 StringIo 和 BytesIO
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情