0%

Python文件

#20 Python文件

前面几节枯燥的模块终于结束了,想要完全掌握前几节的模块需要不断的练习才行,毕竟眼过千遍不如手过一遍嘛。在一些项目需求里,要对文件进行IO操作,毕竟重要数据不可能打印到屏幕上而不去保存,Python对的文件IO操作并不是很复杂,相信你很快就能掌握它!

文件IO操作

对于一个文件的操作,无非不过创建、删除、读、写,创建和删除在OS模块里面已经说过,那只剩下读和写了,也就是IO(Input,Output)操作了。

接下来,将以徐志摩的《再别康桥》为例子,深入解读Python中文件IO操作

轻轻的我走了,

正如我轻轻的来;

我轻轻的招手,

作别西天的云彩。

那河畔的金柳,
是夕阳中的新娘;
波光里的艳影,
在我的心头荡漾。

软泥上的青荇,

油油的在水底招摇;

在康河的柔波里,

我甘心做一条水草!

那榆荫下的一潭,
不是清泉,是天上虹;
揉碎在浮藻间,
沉淀着彩虹似的梦。

寻梦?撑一支长篙,

向青草更青处漫溯⑷;

满载一船星辉,

在星辉斑斓里放歌。

但我不能放歌,
悄悄是别离的笙箫;
夏虫也为我沉默,
沉默是今晚的康桥!

悄悄的我走了,

正如我悄悄的来;

我挥一挥衣袖,

不带走一片云彩。

打开文件

Python获得文件句柄的方式与c及其类似,使用内置函数open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) 「file表示文件名、mode表示打开方式(默认为读)、buffering表示寄存区缓冲大小(负值为系统默认,0为没有寄存区缓存,1为文件会寄存行,大于1的整数为寄存区缓存大小)、encoding表示文件编码、newline表示换行符(默认为)」

1
2
f = open('再别康桥.txt')   # 以默认读的方式打开再别康桥,注意:文件路径(此时程序和再别康桥在同一路径)
f = open('xxx.txt', 'w') # 以写的方式打开文件,注意:如果此文件不存在,则创建这个文件;如果存在,则删除原文件所有内容

对于不同的文件,有不同的处理方式,常用的mode参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
模式                                                描述
r 读
w 写
r+ 读写
w+ 写读
a 追加
a+ 追加读
rb 二进制读
wb 二进制写
rb+ 二进制读写
wb+ 二进制写读
ab 二进制追加
ab+ 二进制追加读

这些模式看似复杂,其实内部规律很清晰,接下来将用文件的读和写来充分了解这些模式

文件的读

read() 「读取文件指针之后的所有内容,并返回字符串」

这里提到了一个新概念:文件指针,想象一下,你在读书,你的手指头指着你正在读的地方,你没读一个字,你的手指头就跟着向后动一下,你的手指头就是文件指针,以上模式中,除了a、a+、ab+文件指针在文件末尾之外,其他的都是在文件开头

1
2
3
4
In [2]: f = open('再别康桥.txt')   # 默认读的方式打开文件

In [3]: f.read() # 读取文件指针之后的所有内容
Out[3]: '轻轻的我走了,\n正如我轻轻的来;\n我轻轻的招手,\n作别西天的云彩。\n----\n那河畔的金柳,\n是夕阳中的新娘;\n波光里的艳影,\n在我的心头荡漾。\n----\n软泥上的青荇,\n油油的在水底招摇;\n在康河的柔波里,\n我甘心做一条水草!\n----\n那榆荫下的一潭,\n不是清泉,是天上虹;\n揉碎在浮藻间,\n沉淀着彩虹似的梦。\n----\n寻梦?撑一支长篙,\n向青草更青处漫溯;\n满载一船星辉,\n在星辉斑斓里放歌。\n----\n但我不能放歌,\n悄悄是别离的笙箫;\n夏虫也为我沉默,\n沉默是今晚的康桥!\n----\n悄悄的我走了,\n正如我悄悄的来;\n我挥一挥衣袖,\n不带走一片云彩。\n'
1
2
3
4
5
6
7
8
9
In [9]: f = open('再别康桥.txt', 'w')   # 以写的模式打开文件,此时这个文件的内容已经被删除了😰

In [10]: f.read() # 可以看到文件是不允许读的
---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
<ipython-input-10-571e9fb02258> in <module>
----> 1 f.read()

UnsupportedOperation: not readable
1
2
3
4
5
6
In [1]: f = open('test.jpg', 'rb')   # 以二进制方式打开文件

In [2]: f.read()
Out[2]: b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xdb\x00C\x00\x05\x04\x04\x05\x04\x03\x05\x05\x04\x05\x06\x06\...........'

# 有许多文件格式是以二进制保存的,最典型的就是图片和视频

readline() 「读一行」

1
2
3
4
5
6
7
8
9
10
11
12
13
In [1]: f = open('再别康桥.txt')

In [2]: f.readline() # 读一行
Out[2]: '轻轻的我走了,\n'

In [3]: f.readline() # 再读一行
Out[3]: '正如我轻轻的来;\n'

In [4]: f.readline()
Out[4]: '我轻轻的招手,\n'

In [5]: f.readline()
Out[5]: '作别西天的云彩。\n'

readlines() 「按行读取文件,将所有的行保存为一个列表」

1
2
3
4
5
In [6]: f = open('再别康桥.txt')

In [7]: f.readlines()
Out[7]:
['轻轻的我走了,\n', '正如我轻轻的来;\n', '我轻轻的招手,\n', '作别西天的云彩。\n', '----\n', '那河畔的金柳,\n', '是夕阳中的新娘;\n', '波光里的艳影,\n', '在我的心头荡漾。\n', '----\n', '软泥上的青荇,\n', '油油的在水底招摇;\n', '在康河的柔波里,\n', '我甘心做一条水草!\n', '----\n', '那榆荫下的一潭,\n', '不是清泉,是天上虹;\n', '揉碎在浮藻间,\n', '沉淀着彩虹似的梦。\n', '----\n', '寻梦?撑一支长篙,\n', '向青草更青处漫溯⑷;\n', '满载一船星辉,\n', '在星辉斑斓里放歌。\n', '----\n', '但我不能放歌,\n', '悄悄是别离的笙箫;\n', '夏虫也为我沉默,\n', '沉默是今晚的康桥!\n', '----\n', '悄悄的我走了,\n', '正如我悄悄的来;\n', '我挥一挥衣袖,\n', '不带走一片云彩。\n']

文件迭代 「open函数打开一个文件后,这个句柄本身是可迭代对象」

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [8]: f = open('再别康桥.txt')

In [9]: for line in f: # 直接迭代文件
...: print(line)
...:
轻轻的我走了,

正如我轻轻的来;

我轻轻的招手,

作别西天的云彩。

----

那河畔的金柳,
(将后面的输出省略了)

文件的写

write(text) 「text表示要写入文件的内容,并返回写入的字符数」

1
2
3
4
5
6
7
In [13]: f = open('new_file.txt', 'w')   # 以写的方式打开文件,如果文件不存在则创建,如果存在则删除原有内容

In [14]: f.write('hello') # 写入hello
Out[14]: 5

In [15]: f.write('word\n') # 写入word并换行
Out[15]: 5

注意:如果这时候去查看文件内容,发现里面还是空荡荡的,为什么呢?因为寄存区缓存的原因,默认是使用系统的寄存区缓存机制,想要立刻写入文件可以改变buffering的值,也可以使用close()方法关闭文件(关闭文件时所有内容都会写入文件)、再或者使用flush()方法立即将寄存区内容写入文件

1
2
3
4
In [23]: f.flush()   # 使用flush()方法立即刷入

In [24]: ! cat new_file.txt # 使用命令查看文件内容,文件内容有两行,一行字,一行空白(因为使用\n换行了),这个是Linux系统命令🤥
helloword
1
2
3
4
5
6
7
8
9
10
In [25]: f = open('new_file.txt', 'a')   # 以追加模式打开,如果文件存在则打开文件,如果不存在则新建文件

In [27]: f.write('i am new\n')
Out[27]: 9

In [28]: f.flush()

In [30]: ! cat new_file.txt
helloword
i am new
1
2
3
4
5
6
7
8
9
In [31]: f = open('new_file.txt', 'a')

In [32]: f.read() # 追加方式是不允许读的,w、wb、ab也不允许读
---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
<ipython-input-32-571e9fb02258> in <module>
----> 1 f.read()

UnsupportedOperation: not readable
1
2
3
4
5
6
7
In [33]: f = open('new_file.txt', 'a+')   # 使用追加读的方式打开文件

In [34]: f.read() # 可以读,但为什么是空的?因为文件指针在末尾
Out[34]: ''

In [36]: f.write('afd') # 也可以写
Out[36]: 3

writelines(lines) 「将一个列表或元组序列写入文件,需要换行自己加」

1
2
3
4
5
6
7
8
9
10
In [39]: f = open('new_file.txt', 'w')

In [43]: f.writelines(['hello','world']) # 将列表序列写入文件

In [44]: f.writelines(('haha','hehe')) # 将元组序列写入文件

In [45]: f.flush() # 刷入

In [46]: ! cat new_file.txt # 查看文件内容
helloworldhahahehe

关闭文件

close() 「关闭文件,如果将寄存区有缓存则写入文件」

1
In [48]: f.close()

文件其他方法

tell() 「返回当前文件指针位置」

seek(offset, whence=0) 「offset代表要设置的文件指针位置」

name 「返回当前文件名」