python读写文件函数_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')

运行结果:

bdadb37063660a1fa685aa86f0165ae9

写文件

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()

运行结果:

5205e6d5d1fe9dfed51f90e41a50d9cb

总结:

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())

62143230193ad37657a515161e1e4ea3

要读取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())

运行结果: 可以看出是一行一行打印出来的

1b3f226ab5da268ecafed2c8e45ffab5

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())

c679310d8c5118f338961a2da8c1d156

和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取:

from io import BytesIO

f=BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')

print(f.read())

29db0abc528a4eef24816f2f201d778b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值