Python I/O编程 --读写文件、StringIO/ BytesIO
I/O编程
Input/Output 输入/输出
Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水
Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去
由于CPU和内存的速度远远高于外设的速度,所以,在I/O编程中,存在速度严重不匹配的问题。例子:比如要把100M的数据写入磁盘(这是output),CPU输出100M只需要0.01s,可是磁盘要接收这100M数据可能需要10s,怎么办呢?有两种解决方法:
第一种:CPU等着,这种模式称为同步IO
第二种:CPU不等着,这种模式称为异步IO
同步和异步的区别:在于是否等待IO执行的结果.
例子:好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等待5分钟, 有两种处理方式:
(1)你站在收银台前等了5分钟,拿到汉堡再去逛商场,这是同步IO
(2)你先逛商场,等做好了,服务员再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO
结论:很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。而服务员如何通知你汉堡做好了,方法各不相同。
(1) 如果是服务员跑过来找你,这是回调模式
(2)如果服务员发短信通知你,你就要不停地检查手机,这是轮询模式
总之,异步IO的复杂度远远高于同步IO
操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外
文件读写
读文件(read)和写文件(write)
注意:由于“ \ ”是字符串中的转义符,所以表示路径时,使用“ \\ ”或者 “ / ”或者“ \\ ”
Python对文本文件和二进制文件采用统一的操作步骤,即“ 打开 - 操作 - 关闭”
读写文件的模式说明:
| 访问模式 | 说明 |
| r | 默认模式,以只读方式打开文件,文件的指针将会放在文件的开头。如果文件不存在,返回异常FileNotFoundError |
| w | 打开一个文件只用于写入。如果文件已存在,则将其覆盖。如果文件不存在,创建新文件 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也即是,新的内容会被追加到已有内容之后。如果文件不存在,创建新文件进行写入。 |
| x | 创建写模式,文件不存在则创建,存在则返回异常FileExistsError |
| t | 文本文件模式,默认值 |
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。 |
| wb | 以二进制格式打开,……(其余的与相应模式的用法相同) |
| ab | 以二进制格式打开,……(其余的与相应模式的用法相同) |
| + | 与r/w/x/a/rb/wb/ab一同使用,在原功能基础上,使其同时具有读写功能 |
| b | 二进制文件模式 |
注意:(追加append)
open( )函数:打开一个文件对象
格式:open( 文件名,文件模式)
文件模式:“r”模式表示读取utf-8编码的文本文件; “rb”模式表示读取二进制文件
文件模式:“w”模式表示写文本文件;“wb”模式表示写二进制文件
二进制文件:图片、视频、声音
字符编码:
读取非utf-8编码的文本文件,使用encoding参数,
文本文件夹杂一些非法编码的字符时,open()函数使用errors参数,表示如果遇到编码错误后如何处理,最简单的方式是直接忽略。
f = open('/Users/michael/notfound.txt', 'rb',encoding='gbk',errors='ignore')
读文件——文件存在
如果文件成功打开,读取文件的方式:
read( )方法:一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示;如果文件有10G,内存就爆了,所以保险起见,可以反复调用read(size)方法。
read(size)方法:每次最多读取size个字节的内容。
readline( ):每次读取一行内容
readlines( ):一次读取所有内容并按行返回一个列表list,列表中的每一个元素为文件中的每一行数据。同时,每一个元素结尾都带一个 \n标志。
readlines(h):参数可选,如果给出,读入h行
读文件——文件不存在
如果文件不存在,ope( )函数会抛出一个IOError错误,并且给出错误码和详细的信息告诉你文件不存在:
f = open('/Users/michael/notfound.txt', 'r')
运行结果:

写文件
f.write( s ):向文件写入一个字符串或字节流。 要显示地使用 ' \n '对写入文本进行分行,如果不进行分行,每次写入的字符串会被连接起来。
f.writelines( lines ):将一个元素为字符串的列表整体写入文件。 直接将列表类型的各元素连接起来写入文件f。
当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
只有调用close( )方法时,操作系统才保证把没有写入的数据全部写入磁盘。
忘记调用close( )的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
close( )方法
文件使用完毕后必须关闭,有两方面原因:
(1)文件对象会占用操作系统的资源。 (2)操作系统同一时间能打开的文件数量也是有限的。
为了保证无论是否出错都能正确地关闭文件,有两种实现方式:
(1)使用try ... finally来实现,因为finally语句块一定会被执行。
(2)with语句:是因为with语句能自动调用close( )方法
使用try ... finally来实现:
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
with语句:
with open('/path/to/file', 'r') as f:
print(f.read())
这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。
文件的定位读写
背景:在实际开发中,可能会需要从文件的某个特定位置开始读写。此时,需要对文件的读写位置进行定位。
两种定位方式:
(1)获取文件当前的读写位置:tell( )方法
(2)定位到文件的指定读写位置:seek (offset, whence )方法
1、使用tell方法来获取文件当前的读写位置
tell方法返回文件的当前位置,即文件指针当前位置
f=open("theima.txt","r")
str=f.read(4)
print("读取的数据是:",str)
#查找当前位置
position=f.tell()
print("当前文件位置:",position)
2、使用seek方法定位到文件的指定读写位置
格式: seek( offset [ , whence ] )
offset:偏移量,即需要移动的字节数
whence表示方向,有三个值:
(1)SEEK_SET或者0:默认值,表示从文件的起始位置开始偏移
(2)SEEK_CUR或者1:表示从文件的当前位置开始偏移
(3)SEEK_END或者2:表示从文件末尾开始偏移
io.UnsupportedOperation: can't do nonzero cur-relative seeks错误
实例:
f=open("E:/test/悯农.txt",'r')
str=f.read(17)
print("读取的数据是:",str)
position=f.tell()
print("当前位置:",position)
f.seek(4,0) #从头开始,偏移4个字节
position=f.tell()
print("当前位置:",position)
f.seek(4,1) #从当前位置开始,偏移4个字节
position=f.tell()
print("当前位置:",position)
f.seek(-4,2)
position=f.tell()
print("当前位置:",position)
f.close()
运行结果:

总结:
seek中whence参数的值:
0:open函数以r,w,带b的二进制模式,就是以任何模式打开文件,都能正常运行
1和2:open函数只能以二进制模式打开文件,才能正常运行,否则就会报出上面的错误
Python的官方文档的解释:
链接地址:https://docs.python.org/3/tutorial/inputoutput.html?highlight=seek
>In text files (those opened without a b in the mode string), only seeks relative to the beginning of the file are allowed (the exception being seeking to the very file end with seek(0, 2)) and the only valid offset values are those returned from the f.tell(), or zero. Any other offset value produces undefined behaviour.
翻译:
在文本文件中(那些在模式字符串中没有b打开的文件),只允许相对于文件的开头进行查找(例外情况是使用seek(0,2)查找文件的结尾),并且唯一有效的偏移值是从f.tell()或零返回的偏移值。任何其他偏移值都会产生未定义的行为。
StringIO和BytesIO
StringIO和BytesIO是在内存中操作str 和bytes(注意:加了s)的方法,使得和读写文件具有一致的接口。
写入时,可以用write 写入,而查看写入的值:使用 getvalue( )函数
读取时,查看值,使用 readline( )、read( )函数
StringIO
只能在内存中操作字符串str
from io import StringIO f=StringIO()
f.write('Hello')
f.write(' , ')
f.write('World')
print(f.getvalue())

要读取StringIO,可以用一个str初始化StringIO,然后,像读文件一样读取:
# read from StringIO:
from io import StringIO
f = StringIO('水面细风生,\n菱歌慢慢声。\n客亭临小市,\n灯火夜妆明。')
while True:
s=f.readline()
if s=="":
break
print('start to print:')
print(s.strip())
运行结果: 可以看出是一行一行打印出来的

BytesIO
BytesIO在内存中读写bytes
注意:1、utf-8编码,使用的是encode参数,中间是英文句号点(.)
2、写入的不是str,而是经过UTF-8编码的bytes。
from io import BytesIO f=BytesIO()
f.write('中文'.encode('utf-8'))
print(f.getvalue())

和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取:
from io import BytesIO
f=BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
print(f.read())

Python I/O编程 --读写文件、StringIO/ BytesIO的更多相关文章
- Python之IO编程——文件读写、StringIO/BytesIO、操作文件和目录、序列化
IO编程 IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口.从 ...
- Python IO编程-读写文件
1.1给出规格化得地址字符串,这些字符串是经过转义的能直接在代码里使用的字符串 需要导入os模块 import os >>>os.path.join('user','bin','sp ...
- Python学习笔记系列——读写文件以及敏感词过滤器的实现
一.读文件 #打开文件,传入文件名和标识符,r代表读 f= open('\\Users\ZC\Desktop\zc.txt','r') #调用read方法一次性读取文件的全部内容,存入内存,用str对 ...
- Python文件读写、StringIO和BytesIO
1 IO的含义 在计算机中,IO是Input/Output的简写,也就是输入和输出. 由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就 ...
- python同步IO编程——StringIO、BytesIO和stream position
主要介绍python两个内存读写IO:StringIO和BytesIO,使得读写文件具有一致的接口 StringIO 内存中读写str.需要导入StringIO >>> from i ...
- Python3 IO编程之文件读写
读写文件是最常见的IO操作.python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一个,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序终结操作磁盘, ...
- Python中IO编程-StringIO和BytesIO
Python在内存中读写数据,用到的模块是StringIO和BytesIO StringIO >>> from io import StringIO >>> f = ...
- media静态文件统一管理 操作内存的流 - StringIO | BytesIO PIL:python图片操作库 前端解析二进制流图片(了解) Admin自动化数据管理界面
一.media ''' 1. 将用户上传的所有静态文件统一管理 -- settings.py -- MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 2. 服务 ...
- python同步IO编程——基本概念和文件的读写
IO——Input/Output,即输入输出.对于计算机来说,程序运行时候数据是在内存中的,涉及到数据交换的地方,通常是磁盘.网络等.比如通过浏览器访问一个网站,浏览器首先把请求数据发送给网站服务器, ...
随机推荐
- .net core 2.0的认证和授权
在asp.net core中,微软提供了基于认证(Authentication)和授权(Authorization)的方式,来实现权限管理的,本篇博文,介绍基于固定角色的权限管理和自定义角色权限管理, ...
- 『摆渡车 斜率优化dp及总结』
摆渡车的题解我已经写过一遍了,在这里,这次主要从斜率优化的角度讲一下摆渡车,并总结一下斜率优化会出现的一些奇奇怪怪的错误. 摆渡车 Description 有 n 名同学要乘坐摆渡车从人大附中前往人民 ...
- css z-index 的学习
前言:这是笔者第一次写博客,主要是学习之后自己的理解.如果有错误或者疑问的地方,请大家指正,我会持续更新! z-index属性描述元素的堆叠顺序(层级),意思是 A 元素可以覆盖 B 元素,但是 B ...
- ML学习笔记之TF-IDF原理及使用
0x00 什么是TF-IDF TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率). # 是一种用于资讯检索与资讯探勘的常用加权技术. ...
- 【WPF】2、美化控件
控件有默认样式,但是有时候默认样式并不够用,就需要美化. 1.常用的方法是美术出图,直接贴图进去,效果又好又简单(对程序来说). 用图片有三种方式:设置控件背景图片.设置控件内容为图片和直接使用图片做 ...
- C# vb .NET读取识别条形码线性条码code39
code39是比较常见的条形码编码规则类型的一种.如何在C#,vb等.NET平台语言里实现快速准确读取该类型条形码呢?答案是使用SharpBarcode! SharpBarcode是C#快速高效.准确 ...
- 1.ZooKeeper ACL权限控制
参考:https://blog.csdn.net/liuxiao723846/article/details/79391650 ZK 类似文件系统,Client 可以在上面创建节点.更新节点.删除节点 ...
- python3 marshmallow学习
python3 marshmallow学习 官方文档:https://marshmallow.readthedocs.io/en/stable/ 安装: pip install -U marshmal ...
- Dubbo(三):框架设计
整体设计 图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口. 图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层 ...
- Django模型层(models.py)之模型创建
Django数据库操作是十分重要的内容,这两天简单学习了数据库的操作,这里做个总结. 1.ORM简介 简单的来说,ORM就是对象-关系-映射.它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖 ...