一、重要概念流
1.从磁盘读取文件到内存就只有input操作,把数据写到文件里就只有output操作。
2.流只能单向流动,Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。所以两个程序之间的数据交换一定得有两条水管(流),而不同程序的处理速度不同(流速不同),应该不是流速,是处理速度不同。假设快递要从a运输到b,a的人多处理速度快,b的人少处理速度慢,a你就不能一直运输。有两种解决办法,一种是同步IO,一种是异步IO,同步就是a的员工先放假,等b处理的差不多了你们在上班,这就是同步,但是老板不同意,我雇你们来不是让你们来放假的,所以安排了a的员工去做其他事,等b处理好了再通知a的员工继续运输快递到b。通知的方式有多种,b的人跑过来a通知,发短信通知等,异比同步要复杂的多。
二、Python的文件读写
1.open()
函数
读写文件前,要先用open()函数打开这个文件,函数可以传入四个参数。
- 第一个是文件的路径,路径要注意转义
- 第二个是标识符
r表示读模式
rb表示读取二进制文件
w表示写模式,如果文件不存在则新创建,存在则重写内容
wb是写二进制文件 - 第三个是字符编码
- 第四个是errors,可以忽略非法编码的字符
#注意这里加r是防止转义,如果没加r,\u啥的就会转义不加就不会。
fpath2 = r'c:\users\ljs\desktop\123.txt'
f = open(fpath2, 'r', encoding = 'utf8' , errors = 'ignore')
#当文件成功打开,我们可以调用read一次读取文件的全部内容,py把内容读到内存,用一个str对象表示
print(f.read())
输出
C:\Users\ljs\Desktop>python io.py
a
b
c
d
e
我们给文件里加入一行f
f.write('\nf')
这时候报错io.UnsupportedOperation: not writable
意思是只调用了r读模式,没有写的权限
我们在前面的open函数的第二个参数换成r+读写模式
f = open(fpath2, 'r+', encoding = 'utf8' , errors = 'ignore')
输出
#因为是先读然后再写,所以交互式里没有显示f,但是f已经写入文件里了
C:\Users\ljs\Desktop>python io.py
a
b
c
d
e
当文件本来有数据,然后要在后面继续添加,这时候是不能用w,因为w会覆盖文件里本来的内容重新写入,要用a(append)
fpath2 = r'c:\users\ljs\desktop\123.txt'
f = open(fpath2, 'w', encoding = 'utf8' , errors = 'ignore')
f.write('h')
你会发现txt里的abcdef全没了,只剩一个h,我们把w改成a就不会出现这样的问题。
最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
f.close()
2.with语句
我们读写的文件可能不存在(路径写错啥的),所以最后的close()可能执行不了,这时候我们就得用try...finally语句块
try:
f = open(r'c:\users\ljs\desktop\123.txt', 'a', encoding = 'utf8' , errors = 'ignore')
f.write('h')
finally:
if f:
f.close()
但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法
with open(r'c:\users\ljs\desktop\123.txt', 'a', encoding = 'utf8' , errors = 'ignore') as f:
f.write('h')
这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。
3.read(size)
假如我们的文件有10g,read()是读取到内存,全部读取内存就会爆炸,所以我们可以多次使用read(size)来读取size个字节的内容。
f = open( r'c:\users\ljs\desktop\123.txt', 'r+', encoding = 'utf8' , errors = 'ignore')
print(f.read(1))
输出
C:\Users\ljs\Desktop>python io2.py
a
我们也可以调研readline()每次读取一行内容,readlines()读取全部内容并按行返回一个list
f = open( r'c:\users\ljs\desktop\123.txt', 'r+', encoding = 'utf8' , errors = 'ignore')
print(f.readline())
print(f.readlines())
输出
C:\Users\ljs\Desktop>python io2.py
a
['b\n', 'c\n', 'd\n', 'e\n', 'f']
如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便
4.读取二进制文件和字符编码
要读取二进制文件,比如图片、视频等等,用'rb'模式
f = open( r'c:\users\ljs\desktop\timg.jpg', 'rb')
print(f.read(10))
输出:
C:\Users\ljs\Desktop>python io2.py
b'\xff\xd8\xff\xe0\x00\x10JFIF'
如果你的文本里有中文即要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件
f = open( r'c:\users\ljs\desktop\123.txt', 'r+', encoding = 'gbk')
print(f.read())
输出
C:\Users\ljs\Desktop>python io2.py
a
b
c
d
e
f
你好
如果encoding是utf8就会报错UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 18: invalid continuation byte
这时候我们不想它报错,我们想让它忽略掉你好,输出前面的就行就可以用到第四个参数errors了
f = open( r'c:\users\ljs\desktop\123.txt', 'r+', encoding = 'utf8', errors = 'ignore')
print(f.read())
输出:
C:\Users\ljs\Desktop>python io2.py
a
b
c
d
e
f
三、总结
1、注意文件读写的顺序。先写再读,如果没有close再open你会读不到。
2、记得每次写操作后的close(),当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,所以最好还是用with语句。
3、温故而知新,每次都会有新发现,等有新发现再补充。
附上一首网易云昨天推荐的歌,Pillow talk。