1 IO的含义

在计算机中,IO是Input/Output的简写,也就是输入和输出。

由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。

比如你访问百度首页,浏览器就需要通过网络IO获取网页。浏览器先会发送请求给百度服务器,告诉它想要的html网址,这个动作是往外发数据,叫Output。接着百度服务器把网页的内容发送过来,这个动作是从外面接收数据,叫Input。

所以,通常,程序完成IO操作会有Input和Output两个数据流。当然也有只用一个的情况,比如,从磁盘读取文件到内存,就只有Input操作,反过来,把数据写到磁盘文件里,就只是一个Output操作。

输入输出是相对的,要考虑具体的对象是什么。一般,当我们写的程序需要读取磁盘文件时,相当于把磁盘的数据输入到程序中,对于程序来说,读取的数据就属于Input,但是对于磁盘来说,相当于把数据输出给程序,输出的数据属于Output。

IO编程中,Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。对于浏览网页来说,浏览器和服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据。

由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。举个例子来说,比如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,可是磁盘要接收这100M数据可能需要10秒,怎么办呢?有两种办法:

第一种是CPU等着,也就是程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行,这种模式称为同步IO。
另一种方法是CPU不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步IO。
同步和异步的区别就在于是否等待IO执行的结果。好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等5分钟,于是你站在收银台前面等了5分钟,拿到汉堡再去逛商场,这是同步IO。

你说“来个汉堡”,服务员告诉你,汉堡需要等5分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO。

很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。想想看,你得知道什么时候通知你“汉堡做好了”,而通知你的方法也各不相同。如果是服务员跑过来找到你,这是回调模式,如果服务员发短信通知你,你就得不停地检查手机,这是轮询模式。总之,异步IO的复杂度远远高于同步IO。

操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。

读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。

读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

2 读文件
要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符:

>>> f = open('C:\\Users\\hfqn\\Desktop\\test.txt', 'r')

标示符’r’表示读,这样,我们就成功地打开了一个文件。

如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在:

>>> f=open('C:\\Users\\hfqn\\Desktop\\notfound.txt', 'r')
Traceback (most recent call last):File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\hfqn\\Desktop\\notfound.txt'

如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示:

>>> f.read()
'Hello, world!'

最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的:

>>> f.close()

由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try … finally来实现:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
try:f = open('\path\to\file', 'r')print(f.read())
finally:if f:f.close()

但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:

with open('\path\to\file', 'r') as f:print(f.read())

这和前面的try … finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。

调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,为保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。

另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。

如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
with open('\path\to\file', 'r') as f:for line in f.readlines():print(line.strip())         # 把末尾的'\n'删掉

前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用’rb’模式打开文件即可:

>>> f = open('C:\\Users\\hfqn\\Desktop\\test.jpg', 'rb')
>>> f.read()
b''\x89PNG\r\n\x1a\n\x00\x00\x00...'     # 十六进制表示的字节

要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

>>> f = open('C:\\Users\\hfqn\\Desktop\\gbk.txt','r',encoding='gbk')
>>> f.read()
'人生苦短,我用python'

遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

>>> f = open('C:\\Users\\hfqn\\Desktop\\gbk.txt','r',encoding='gbk', errors='ignore')

3 写文件

写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
>>> f = open('C:\\Users\\hfqn\\Desktop\\test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()

你可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。

当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:

with open('C:\\Users\\hfqn\\Desktop\\test.txt', 'w') as f:f.write('Hello, world!')

要写入特定编码的文本文件,请给open()函数传入encoding参数,将字符串自动转换成指定编码。

4 StringIO和BytesIO

很多时候,数据读写不一定是文件,也可以在内存中读写。StringIO就是在内存中读写str。

要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!

getvalue()方法用于获得写入后的str。

要读取StringIO,可以用一个str初始化StringIO,然后,像读文件一样读取:

>>> from io import StringIO
>>> f = StringIO('Hello!\nHi!\nGoodbye!')
>>> while True:
...     s = f.readline()
...     if s == '':
...         break
...     print(s.strip())Hello!
Hi!
Goodbye!

StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。

BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(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的方法,使得和读写文件具有一致的接口。

Python文件读写、StringIO和BytesIO相关推荐

  1. python文件读写_python基础-文件读写'r' 和 'rb'区别

    一.Python文件读写的几种模式: r,rb,w,wb 那么在读写文件时,有无b标识的的主要区别在哪里呢? 1.文件使用方式标识 'r':默认值,表示从文件读取数据. 'w':表示要向文件写入数据, ...

  2. 肝!超好懂的 Python 文件读写教程!

    (扫码关注) 作者:黄伟呢 源自:数据分析与统计学之美 1.文件读写的流程 1)类比windows中手动操作txt文档,说明python中如何操作txt文件? ① windows中手动操作txt文件的 ...

  3. python文件读取模式_day-2 python 文件读写模式r,r+,w,w+,a,a+的区别

    r+和w+都是可读可写,区别在于r+读文件时,不会覆盖之前的内容,之前的内容能够读出来:w+读时,会覆盖之前的内容:所以读文件时,用r或者r+ #读操作 r 1 filepath = 'aa.log' ...

  4. Python 文件读写

    Python 文件读写 Python内置了读写文件的函数,用法和C是兼容的.本节介绍内容大致有:文件的打开/关闭.文件对象.文件的读写等. 本章节仅示例介绍 TXT 类型文档的读写,也就是最基础的文件 ...

  5. Python 文件读写操作-Python零基础入门教程

    目录 一.Python 文件的打开 open 二.Python 文件的关闭 close 三.Python 文件的读取 read 1.read 函数 2.readline 函数 3.readlines ...

  6. python文件读写及形式转化和CGI的简单应用

    一丶python文件读写学习笔记 open() 将会返回一个 file 对象,基本语法格式如下: open(filename, mode) filename:包含了你要访问的文件名称的字符串值. mo ...

  7. seek是python文件操作方法吗,seek引发的python文件读写的问题

    我的需求很简单,就是统计一下我的安装脚本执行的次数和时间,格式是这样的 install_times:1|install_times:2018-09-03 15:58:46 install_times: ...

  8. python异步读写文件_一文彻底搞懂python文件读写

    Python文件读写 一,I/O操作 I/O在计算机中是指Input/Output,也就是Stream(流)的输入和输出.这里的输入和输出是相对于内存来说的,Input Stream(输入流)是指数据 ...

  9. python 文件读写with open模式r,r+ w,w+ a,a+区别详解

    python 文件读写with open模式r,r+ w,w+ a,a+区别详解 python中的 with open主要要来进行文件读写的操作 在 Python 中使用文件的关键函数是 open() ...

  10. python 输出文件分隔符_使用Python文件读写,自定义分隔符的方法

    使用Python文件读写,自定义分隔符的方法 发布时间:2020-07-06 11:07:56 来源:亿速云 阅读:121 作者:清晨 小编给大家分享一下使用Python文件读写,自定义分隔符的方法, ...

最新文章

  1. python:文件操作
  2. 华为新版交换机端口配置由TRUNK改为ACCESS
  3. Table-values parameter(TVP)系列之一:在T-SQL中创建和使用TVP
  4. C#中Socket通信编程的异步实现
  5. Tornado 高并发源码分析之六---异步编程的几种实现方式
  6. 防盗链与token运用
  7. Call to localhost/127.0.0.1:9000 failed on connection exception:java.net.ConnectException的解决方案
  8. python之函数用法capitalize()
  9. hosts文件修改完无效的解决办法
  10. mapper mysl实现批量插入 更新
  11. 显示器最大分辨率测试软件,液晶显示器分辨率快速设置工具
  12. 千方百剂医药管理系统对接第三方WMS系统(天力士物流)
  13. pyqt html编辑器,PyQt笔记——代码编辑器Scintilla的使用方法
  14. OpenCV中文官方文档-分享
  15. ecshop 在确认收货时新增加商品评价并送消费积分功能
  16. javax.crypto.BadPaddingException Given final block not properly padded?
  17. 2022年Java就业方向有哪些?
  18. win python 判断 所有 子进程 结束_python 多进程如何终止或重启子进程?
  19. openpyxl中的load_workbook()函数
  20. 【IO/NIO】Java NIO浅析

热门文章

  1. LBaaS 实现机制 - 每天5分钟玩转 OpenStack(125)
  2. Linux CentOS下配置SVN+SVN勾子
  3. Kali Linux GRUB修复
  4. 编程的一些快捷键(转帖)
  5. 利用kickstart实现pxe的自动化安装
  6. Centos用cron定时执行PHP
  7. 菜鸟也玩WebMatrix
  8. 如何获取尚未开票信息(包括交货单、销售订单)
  9. FD33里面的销售值不正确应该怎么办?
  10. ERROR: 资源短缺 PXA_NO_FREE_SPACE