在平时,我们不光要对程序内的代码进行输入和输出的操作,还要对程序外的文件进行和语言之间的交换、操作和运算。在基础部分,先讲解对于外部的.txt文件的操作。
第一部分 基本内容讲解
1. 什么是文件操作?
平时在进行操作的时候,都是在内存层面进行操作,但是随着程序的关闭,信息也将小时。文件操作的方式就是把操作的内容保存在硬盘上,方便随时进行增、删、改、查的操作。
2. 操作流程
(1) 打开文件,得到文件句柄并赋值给一个变量(有一个函数f.fileno(),查看当前的操作句柄编码)。在这里我们要有句柄的概念,在语言中,文件从外部获取后,通过句柄取拿取文件想要的内容。
(2) 通过句柄对文件进行操作。
(3) 关闭文件(这个操作是必须的)。
3. 注意:
(1) 比如在window系统,一个hello.txt文件是utf8保存的,打开文件是open函数是通过操作系统打开文件,而windows操作系统默认是gbk编码,所以直接打开会乱码,需要f = open('hello.txt', encoding = 'utf-8'),这样打开。
(2) 文件的操作还要有指针的概念,通过指针读写光标的位置(内部指针的移动)。
第二部分 相关函数和操作演示
1. 基本函数
函:f.fileno
语:f.fileno()
用:获得当前函数句柄的编号。
1 f = open("咏梅", "r", encoding="utf-8") 2 fno = f.fileno() 3 print(fno) 4 # print(f.fileno()) # 也可以直接打印观察 5 # 输出结果:3 6 7 f1 = open("咏梅", "r", encoding="utf-8") 8 fno1 = f1.fileno() 9 print(fno1) 10 # print(f1.fileno()) # 也可以直接打印观察 11 # 输出结果:4
函:f.name
语:f.name()
用:获得当前文件的文件名。
举例:略
2. 四个基本操作:开、读、写、关
“开”:
函:open
语:open("file", "mode", buffering =None , encoding = None, errors = None, newline = None, closefd = True)
用:
(1) "file"----文件名/路径+文件名 (如果是相对路径直接填写文件名即可),需要加引号
(2) "mode"----读取模式:
"r"---- 只读模式
"w"---- 写模式
"a"---- 追加内容模式(光标位置在最后)
"x" ---- 打开一个单独创作的文件,如果失败将会返回。
"t" ---- 以文本模式打开(缺省模式)
"b" ---- 二进制模式
"U" ---- 通用换行符
"rb" ---- 读取二进制文件
"wb" --- 写二进制文件
"ab" ---- 追加二进制文件
"+" ---- 加模式用于下面的几种组合:
"r+"---- 读写/写读模式(光标位置不同), 属于加模式下
"w+"---- 写读/读写模式(光标位置不同), 属于加模式下
"a+"---- 追读/读追模式(光标位置不同), 属于加模式下
(3) buffering = ---- 可取的值有0、1、>1 三种,0表示buffer关闭(只适用于二进制模式),1代表line buffer(只适用于文本模式),>1表示初始化的buffer大小。
(4) encoding = ---- 编码模式
(5) errors = ---- 错误忽略模式(取值一般有strict、ignore,replace,当取strict的时候,字符编码出现问题的时候会报错,当取ignore的时候,编码出现问题,程序会忽略而过,绩效执行下面的程序。选择replace的时候,使用某字符进行替代模式,比如使用?来替代出错。)
(6) newline = ---- 可取的值有None, 、 、"、' ',用于区分换行符,但是这个参数只对文本有效。
(7) closefd = ---- 默认情况下是True。是与传入的文件参数有关,传入file参数为文件的文件名,取值为false的时候,file只能是文件描述符,什么是文件描述?就是一个非负的整数,在Unix内核的系统中,打开一个文件,变回返回一个文件描述。
“读”:
函:f.read、f.readline、f.readlines、f.readable
语:f.read(n)、f.readline(n)、f.readlines(n)、f.readable
用:f.read(n):默认为读取文本中所有的内容,n为从开始读几个字符。输出为字符串格式。
f.readline(n):默认为读取文本的第一行内容,n为某一行开始读几个字符。输出为字符串格式。
f.readlines(n):默认按照行的排列,读取所有的行,n为对应所有字符的位置,如果当前字符位在某一行内,直接返回读取到当前的行。输出为列表类型。
f.readable():判断句柄文字是否可读,返回真True或者False。
“写”:
函:f.write、f.writelines、f.writeable
语:f.write("str")、f.writelines(list)、f.writeable()
用:f.write("str"):写入括号字符串中的内容。
f.writelines(list):根据一个列表内容添加到文本中。跟上面的f.realines一样,f.realines是把内容读出到列表中;f.writelines是把列表添加到文本中。
f.writeable:返回值为False或者True,表示当前句柄内容是否可写。
“关”:
函:f.close
语:f.close()
用:关闭一个文档。
3. 根据上面的四类函数进行详细的讲解
3.1 一个最简单的操作并读取文件的过程。
代码如下:
1 # 一个简单的打开和操作 # 2 # 第一种打开方式:"r":只读模式 3 data = open("咏梅", "r", encoding="utf-8").read() 4 print(data) 5 print(type(data), " ") 6 # 输出结果: 7 # 风雨送春归, 8 # 飞雪迎春到。 9 # 已是悬崖百丈冰, 10 # 犹有花枝俏。 11 # 12 # 俏也不争春, 13 # 只把春来报。 14 # 待到山花烂漫时, 15 # 她在丛中笑。 16 # <class 'str'> 17 18 # 第二种打开方式:采用函数句柄的方式打开文件。"r":只读模式 19 f = open("咏梅", "r", encoding="utf-8") 20 data = f.read() 21 print(data) 22 print(type(data), " ") 23 # 输出结果: 24 # 风雨送春归, 25 # 飞雪迎春到。 26 # 已是悬崖百丈冰, 27 # 犹有花枝俏。 28 # 29 # 俏也不争春, 30 # 只把春来报。 31 # 待到山花烂漫时, 32 # 她在丛中笑。 33 # <class 'str'>
分析知识点:
(1) 第一种方式为用只读方式简单的打开了一个文件,采用面向对象类的访问方式.read()的方式打开文件。
(2) 第二种方式,用open函数打开文件后,赋值到一个句柄f当中,后面的所有操作都是根据句柄f展开的。我们看到这两种方式效果一样,但是建议采用后者,逻辑更清晰。
(3) open函数一种最常用的格式为open("文件名", "读取模式", “编码格式”),这个必须记住。
(4) 在这里我们用到了f.read的函数,根据另外两个read函数进行演示,以第二种方式为例。
代码如下:
1 # 例子1:只读取前三个字符(英文1个单词一个字符,中文1个字两个字符) 2 # 方法一: 3 f = open("咏梅", "r", encoding="utf-8") 4 data = f.read(3) 5 print(data) 6 print(type(data)) 7 # 输出结果: 8 # 风雨送 9 # <class 'str'> 10 11 # 方法二: 12 f = open("咏梅", "r", encoding="utf-8") 13 data = f.readline(3) 14 print(data) 15 print(type(data)) 16 # 输出结果: 17 # 风雨送 18 # <class 'str'> 19 20 # 例子2:用列表形式读取所有的内容 21 f = open("咏梅", "r", encoding="utf-8") 22 data = f.readlines() 23 print(data) 24 print(type(data)) 25 # 输出结果: 26 # ['风雨送春归, ', '飞雪迎春到。 ', '已是悬崖百丈冰, ', '犹有花枝俏。 ', ' ', '俏也不争春, ', '只把春来报。 ', '待到山花烂漫时, ', '她在丛中笑。'] 27 # <class 'list'> 28 29 # 例子3:用列表的形式只读取前两行内容 30 f = open("咏梅", "r", encoding="utf-8") 31 data = f.readlines() 32 print(data[0:2]) 33 print(type(data)) 34 # 输出结果: 35 # ['风雨送春归, ', '飞雪迎春到。 '] 36 # <class 'list'> 37 38 # 例子4:用列表的形式只读取前两行内容,并把内容转换成字符串形式。 39 f = open("咏梅", "r", encoding="utf-8") 40 data = f.readlines() 41 data1 = data[0] 42 data2 = data[1] 43 data3 = data1 + data2 44 print(str(data3)) 45 print(type(data3)) 46 # 输出结果: 47 # 风雨送春归, 48 # 飞雪迎春到。 49 # 50 # <class 'str'>
分析知识点:
(1) 从f.readlines和f.readline函数中我们可以看到f.readlines这个函数返回的结果是list(列表)类型,然后再通过查找列表的第几个元素,就是对应的第几行。
(2) python对于选取行数的方式用转移成list的方式进行实习,通过list的下标再找到第几行。
3.2 借用上面的例子,把读取的文件在最后光标位添加内容。
代码如下:
1 # 例子1:在咏梅这首诗光标最后位置添加一段内容。 2 f = open("咏梅", "a+", encoding="utf-8") 3 data = f.write("大将生来胆气寒") 4 f.seek(0) # 这个函数下面会讲 5 data1 = f.read() # 这个时候文件指针放到最后一个字符,要用seek恢复指针。 6 print(data1) 7 f.close() 8 # 输出结果: 9 # 风雨送春归, 10 # 飞雪迎春到。 11 # 已是悬崖百丈冰, 12 # 犹有花枝俏。 13 # 14 # 俏也不争春, 15 # 只把春来报。 16 # 待到山花烂漫时, 17 # 她在丛中笑。大将生来胆气寒 # 在结尾出添加了一句话。 18 19 # 例子2:在结尾处的下一行添加一段内容。 20 f = open("咏梅", "a+", encoding="utf-8") 21 data = f.write(" 大将生来胆气寒") # 在开始添加一个换行符 22 f.seek(0) # 这个函数下面会讲 23 data1 = f.read() # 这个时候文件指针放到最后一个字符,要用seek恢复指针。 24 print(data1) 25 f.close() 26 # 输出结果: 27 # 风雨送春归, 28 # 飞雪迎春到。 29 # 已是悬崖百丈冰, 30 # 犹有花枝俏。 31 # 32 # 俏也不争春, 33 # 只把春来报。 34 # 待到山花烂漫时, 35 # 她在丛中笑。 36 # 大将生来胆气寒 # 添加在这里 37 38 # 例子3:观察打开的文件是否可写,如果可写用f.writelines的方式添加另外一首诗进去。 39 # 然后判断句柄是否可读,如果可读把文章读出来。 40 f = open("咏梅", "a+", encoding="utf-8") 41 if f.writable() == True: # 判断文章是否可写 42 list = [" 锄禾日当午,", " 汗滴禾下土。", " 谁知盘中餐,", " 粒粒皆辛苦。"] 43 f.writelines(list) 44 f.seek(0) 45 if f.readable() == True: # 判断文章是否可读 46 data = f.read() 47 print(data) 48 f.close() 49 # 输出结果: 50 # 风雨送春归, 51 # 飞雪迎春到。 52 # 已是悬崖百丈冰, 53 # 犹有花枝俏。 54 # 55 # 俏也不争春, 56 # 只把春来报。 57 # 待到山花烂漫时, 58 # 她在丛中笑。 59 # 60 # 锄禾日当午, 61 # 汗滴禾下土。 62 # 谁知盘中餐, 63 # 粒粒皆辛苦。
分析知识点:
(1) f.writelines对应上面的f.readlines返回的值都是list列表类型,通过写一个list列表可以多行来进行添加。
(2) f.seek移动光标位置,如果不移动的话,将读取不了文件。
(3) f.close()这个千万不要忘记。
3.3 回过头来我们在把open的其他几个填充参数讲解一下
buffering:
buffering选项是一个可选参数,平时很少用到。但是这里进行讲解一下。
buffering用来表示缓冲区的策略选择。设置为0时,表示不使用缓冲区,直接读写,尽在二进制模式下有效。设置为1时,表示在文本模式下使用行缓冲区方式。设置为大于1时,表示缓冲区的设置大小,如果参数buffering没有给出,会使用默认策略进行选择,方式如下:
(1) 对于二进制模式时,采用固定块内缓冲区方式,内存块的大小根据系统设置的分配磁盘块来决定,如果获取系统磁盘块的大小失败,就是用内部常量io.DEFAULT_BUFFER_SIZE定义大小。一般的操作系统上,快的大小是4096或者8192自己大小。
(2) 对于交互式的文本采用isatty()(检测当期设备函数)来判断为True时,采用一行缓冲区的方式。其他文本文件使用跟二进制一样的方式。
总结:换句话说基本没用。
errors:
errors选项是用来知名编码和解码错误时怎么处理。不能再二进制的模式下使用。
(1) 当指明为 strict 时,编码出错则跑出异常ValueError
(2) 当指明为 ignore 时,忽略错误。
(3) 当指明为 replace 时,使用某字符进行替代模式,比如使用?来替换出错。
我们还是用咏梅那首诗,我们开始采用的编码是utf-8编码,如果我们替换成ASCII码的解码方式,肯定是个错误,如果错误的话,分别对应这三种结果会产生什么效果。
代码如下:
1 # errors 2 # 使用strict 严格方式。 3 f = open("咏梅", "r", errors="strict", encoding="ASCII") 4 data = f.read() 5 print(data) 6 # 输出结果: 7 # 产生一个报错,不应是用ASCII码来进行解码 8 # Traceback (most recent call last): 9 # File "C:/Users/Administrator/Desktop/Python-1704/day5/文件操作.py", line 221, in <module> 10 # data = f.read() 11 # File "F:UsersAdministratorPycharmProjectsuntitledvenvlibencodingsascii.py", line 26, in decode 12 # return codecs.ascii_decode(input, self.errors)[0] 13 # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128) 14 15 # 使用 ignore 忽略方式。 16 f = open("咏梅", "r", errors="ignore", encoding="ASCII") 17 data = f.read() 18 print(data) 19 # 输出结果: 20 # 啥都没有显示,这个解码错误被忽略了。 21 22 # 使用 replace 替换方式。 23 f = open("咏梅", "r", errors="replace", encoding="ASCII") 24 data = f.read() 25 print(data) 26 # 输出结果: 27 # 一堆问号,错误解码用?来替代 28 # ������������������ 29 # ������������������ 30 # ������������������������ 31 # ������������������ 32 # 33 # ������������������ 34 # ������������������ 35 # ������������������������ 36 # ������������������
newline:
newline是用来控制文本模式之下一行的结束字符。可以是None,' ', , , 等。在当读取模式下,如果新行符为None,那么就作为通用换行符模式工作,一是是说当遇到 , 或者 都可以作为换行标识,并统一转换为 作为文本输入换行符。当设置为空' ' 时,也就是通用换行符模式工作,但不作转换为 ,输入什么样,就保持原样全输入。当设置为其他相应字符时,就会判断到相应的字符作为换行符,并保持原样输入到文本。
当输出模式时,如果新行符为None,那么所有输出文本都是采用 作为换行符。如果设置为' '空或者 时,不做任何替换动作。如果是其他字符,会出现在字符后面添加 作为换行符。
这个功能也是不太常用的,而且python3中,只能用f.readlines进行演示演示代码如下:
1 # 如果默认None状态 2 f = open("咏梅", "r+", encoding="utf-8", newline=None) 3 data = f.readlines() 4 print(data) 5 # 输出结果:正常显示 6 # ['风雨送春归, ', '飞雪迎春到。 ', '已是悬崖百丈冰, ', '犹有花枝俏。 ', ' ', '俏也不争春, ', '只把春来报。 ', '待到山花烂漫时, ', '她在丛中笑。 '] 7 8 # 如果" "的状态 9 f = open("咏梅", "r+", encoding="utf-8", newline=" ") 10 data = f.readlines() 11 print(data) 12 # 输出结果:用 替代换行符 ,而 提到前面去了。 13 # ['风雨送春归, ', ' 飞雪迎春到。 ', ' 已是悬崖百丈冰, ', ' 犹有花枝俏。 ', ' ', ' 俏也不争春, ', ' 只把春来报。 ', ' 待到山花烂漫时, ', ' 她在丛中笑。 ', ' '] 14 15 # 如果" "的状态 16 f = open("咏梅", "r+", encoding="utf-8", newline=" ") 17 data = f.readlines() 18 print(data) 19 # 输出结果: 都表示换行 20 # ['风雨送春归, ', '飞雪迎春到。 ', '已是悬崖百丈冰, ', '犹有花枝俏。 ', ' ', '俏也不争春, ', '只把春来报。 ', '待到山花烂漫时, ', '她在丛中笑。 '] 21 22 # 如果" "的状态 23 f = open("咏梅", "r+", encoding="utf-8", newline=" ") 24 data = f.readlines() 25 print(data) 26 # 输出结果: 都表示换行跟上面一样 27 # ['风雨送春归, ', '飞雪迎春到。 ', '已是悬崖百丈冰, ', '犹有花枝俏。 ', ' ', '俏也不争春, ', '只把春来报。 ', '待到山花烂漫时, ', '她在丛中笑。 '] 28 29 # 如果""的状态 30 f = open("咏梅", "r+", encoding="utf-8", newline="") 31 data = f.readlines() 32 print(data) 33 # 输出结果:与上面一个一样。 34 # ['风雨送春归, ', '飞雪迎春到。 ', '已是悬崖百丈冰, ', '犹有花枝俏。 ', ' ', '俏也不争春, ', '只把春来报。 ', '待到山花烂漫时, ', '她在丛中笑。 ']
closefd:
是否关闭,用来给当一个文件句柄传进来时,而当退出文件使用时,而不对文件句柄进行关闭。如果传递一个文件名进来,这个参数无效,必定为True方式。
如果为True时:传入的file参数为文件的文件名
如果为False时:传入的file参数只能是文件描述符。
如果Ps:文件描述,就是一个非负整数,在Unix内核的系统中,打开一个文件,变回返回一个文件描述。
4. 剩下一点儿就是对于mode的模式几种进行一下说明
4.1 基本模式:
"r"----只读模式,代码如下:
1 # 只读模式 2 f = open("咏梅", "r", encoding="utf-8") 3 data = f.read() 4 print(data) 5 f.close() 6 # 输出结果: 7 # 风雨送春归, 8 # 飞雪迎春到。 9 # 已是悬崖百丈冰, 10 # 犹有花枝俏。 11 # 12 # 俏也不争春, 13 # 只把春来报。 14 # 待到山花烂漫时, 15 # 她在丛中笑。
分析知识点:没啥可说的,也就是打开文件只能读
"w"----只写模式:
1 # 只写模式 2 f = open("二进制文件.txt", "w", encoding="utf-8") 3 data = f.read() 4 print(data) 5 f.close() 6 # 输出结果: 7 # Traceback (most recent call last): 8 # File "C:/Users/Administrator/Desktop/Python-1704/day5/文件操作.py", line 308, in <module> 9 # data = f.read() 10 # io.UnsupportedOperation: not readable
分析知识点:
(1) 如果原文件不存在,文件名作为新建文件名且创建一个新的文件。
(2) 如果源文件存在,会把原文件的内容全部覆盖掉,作为一个空文件以供添加内容。
(3) 由于是只写模式,所以下面输出结果会报错。
"a"----追加模式:
1 # 追加模式 2 f = open("咏梅", "a", encoding="utf-8") 3 data = f.write("作者:毛主席") 4 print(data) 5 f.close() 6 # 输出模式: 7 # 6 8 # 文件中显示: 9 # 风雨送春归, 10 # 飞雪迎春到。 11 # 已是悬崖百丈冰, 12 # 犹有花枝俏。 13 # 14 # 俏也不争春, 15 # 只把春来报。 16 # 待到山花烂漫时, 17 # 她在丛中笑。("a"模式打开后,指针位与这个位置)作者:毛主席
分析知识点:注意一点"a"模式,指针开始会停留在最后一个字符的后面,也就是说,不添加换行等命令。是在最后一个位置进行添加。
"U" ---- 通用换行符模式打开,---也就是rU简写是r等。
"t" ---- 以文本模式打开(缺省模式)----也就是rt简写是r, wt简写是w,这个字符可以省略
"b" ---- 二进制模式如下:
"rb" ---- 读取二进制文件:
"wb" --- 写二进制文件:
"ab" ---- 追加二进制文件:
1 # rb模式 2 f = open("咏梅", "rb") 3 # f.read() 4 data = f.read() 5 print(data) 6 #print(f) # 直接打印句柄,会显示描述文件<_io.BufferedReader name='咏梅'> 7 # print(f.read()) # 这样还直接打印不了,显示为:b'' 8 f.close() 9 # 输出结果: 10 # b'xe9xa3x8exe9x9bxa8xe9x80x81xe6x98xa5xe5xbdx92xefxbcx8c xe9xa3x9exe9x9bxaaxe8xbfx8exe6x98xa5xe5x88xb0xe3x80x82 xe5xb7xb2xe6x98xafxe6x82xacxe5xb4x96xe7x99xbexe4xb8x88xe5x86xb0xefxbcx8c xe7x8axb9xe6x9cx89xe8x8axb1xe6x9ex9dxe4xbfx8fxe3x80x82 xe4xbfx8fxe4xb9x9fxe4xb8x8dxe4xbax89xe6x98xa5xefxbcx8c xe5x8fxaaxe6x8ax8axe6x98xa5xe6x9dxa5xe6x8axa5xe3x80x82 xe5xbex85xe5x88xb0xe5xb1xb1xe8x8axb1xe7x83x82xe6xbcxabxe6x97xb6xefxbcx8c xe5xa5xb9xe5x9cxa8xe4xb8x9bxe4xb8xadxe7xacx91xe3x80x82' 11 # 一连串的二进制地址位。 12 13 # wb模式 14 f = open("二进制文件", "wb") 15 f.write(b'xe9xa3x8exe9x9bxa8') 16 f.close() 17 # 文本中的输出结果: 18 # 风雨 这两个汉字 19 20 # ab模板 21 f = open("二进制文件", "ab") 22 f.write(b"xe9x80x81xe6x98xa5") 23 f.close() 24 # 文本中的输出结果: 25 # 风雨送春 在风雨的后面又追加两个汉字
分析知识点:
(1) 从这三个例子可以看出,二进制的输入要用二进制地址格式进行输入,像b"地址" 或者 b'地址' 这样才能去写,写到文本中后,会自动变为字符。
(2) 二进制读取读取出来的也是像b"地址" 或者 b'地址'这样的二进制地址位。
(3) 如果在某一个模式下,直接print(f)句柄,会得到os.BufferedReader缓冲区对于文件的简要描述
(4) 如果直接打印print(f.write())这样的句柄模式,会得到输入了多少个字符。如果打印print(f.read())会全部内容。
"+" ---- 加模式如下:
"r+"---- 读写/写读模式,先读后写
1 # r+模式 两种变化 2 # 第一种:先写后读,指针从0行0位开始进行写,之前写的不动,会根据添加的字符进行不断的覆盖。 3 f = open("二进制文件", "r+", encoding="utf-8") 4 f.write("作者:毛主席 作者:毛主席 ") 5 print(f.read()) 6 f.close() 7 # 文本显示结果: 8 # 作者:毛主席 # 把前两行覆盖了 9 # 作者:毛主席 10 # 已是悬崖百丈冰, 11 # 犹有花枝俏。 12 # 13 # 俏也不争春, 14 # 只把春来报。 15 # 待到山花烂漫时, 16 # 她在丛中笑。 17 18 # 第二种:先读后写,指针从0行0位读到最后一个字符的后, 这个时候写的话,变成追加模式了。 19 f = open("二进制文件", "r+", encoding="utf-8") 20 print(f.read()) 21 f.write("作者:毛主席") 22 f.close() 23 # 文本显示结果: 24 # 风雨送春归, 25 # 飞雪迎春到。 26 # 已是悬崖百丈冰, 27 # 犹有花枝俏。 28 # 29 # 俏也不争春, 30 # 只把春来报。 31 # 待到山花烂漫时, 32 # 她在丛中笑。作者:毛主席 # 此时指针读完,放到最后,进行追加了。
分析知识点:
(1) r+模式是r + w 模式的组合。
(2) r+模式注意指针的变化。
"w+"---- 写读/读写模式
1 # w+ 模式 2 f = open("二进制文件", "w+", encoding="utf-8") 3 f.write("作者:毛主席") 4 f.close() 5 # 文本中显示结果: 6 # 作者:毛主席
分析知识点:
(1) w+模式是w + r 模式的组合。
(2) w+模式注意指针的变化。
"a+"---- 追读/读追模式
1 # a+ 模式 2 f = open("二进制文件", "a+", encoding="utf-8") 3 str = [" 风雨送春归,", " 飞雪迎春到"] 4 f.writelines(str) 5 f.close() 6 # 文本中显示结果: 7 # 作者:主席 8 # 风雨送春归, 9 # 飞雪迎春到
分析知识点:
(1) a+模式是a + r 模式的组合。
(2) a+模式注意指针的变化。
第三部分 其他文件的操作方法
1. 遍历打印方式
之前我们知道用f.readlines()是输出了一个列表的形式,我们前面的代码访问具体的内容是用下标的方式,其实我们也可以用for遍历的方式也是一样的。
用简单for循环的方式进行遍历,代码如下:
1 # 遍历的方式打印所有的行 2 f = open("咏梅", "rt", encoding="utf-8") 3 for i in f.readlines(): 4 print(i.strip()) # 如果不加strip,会多换一行,一般要加上一个strip()保持和原先文章一致 5 # 输出结果: 6 # 风雨送春归, 7 # 飞雪迎春到。 8 # 已是悬崖百丈冰, 9 # 犹有花枝俏。 10 # 11 # 俏也不争春, 12 # 只把春来报。 13 # 待到山花烂漫时, 14 # 她在丛中笑。
用列表的方式进行遍历,代码如下:
1 # 用列表的方式 进行遍历 2 f = open("咏梅", "rt", encoding="utf-8") 3 f = f.readlines() 4 num = 0 5 while num < len(f): 6 print(f[num].strip()) 7 num += 1
用枚举的方式进行遍历,代码如下:
1 # 用枚举的方式进行遍历 2 f = open("咏梅", "rt", encoding="utf-8") 3 for i, v in enumerate(f.readlines(), 1): # 这是for 内部将f对象做成一个迭代器,用一行取一行 4 print(i, v.strip()) 5 print(type(i)) 6 print(i) # 迭代到最后一行 7 # 显示结果: 8 # 1 风雨送春归, 9 # 2 作者:毛主席 10 # 3 飞雪迎春到。 11 # 4 已是悬崖百丈冰, 12 # 5 犹有花枝俏。 13 # 6 14 # 7 俏也不争春, 15 # 8 只把春来报。 16 # 9 待到山花烂漫时, 17 # 10 她在丛中笑。 18 # <class 'int'> 19 # 10
分析知识点:在这里遍历打印的时候i.strip()是常用的一种技巧,目的是为了在strip前后无效的 这些位置去除掉。
2. 我们把咏梅的诗歌,第二行显示“作者:毛主席”,然后把第二行的毛主席显示一个字符串,用两种方式:
代码如下:
1 # 方法一:传统方法 2 f = open("咏梅", "rt", encoding="utf-8") 3 num = 0 4 for i in f.readlines(): 5 num += 1 6 if num == 2: # 如果读到第二行 7 print(i.strip(), end=" 你回答的很正确") 8 else: 9 print(i.strip()) 10 f.close() 11 # 显示结果: 12 # 风雨送春归, 13 # 作者:毛主席 你回答的很正确飞雪迎春到。 14 # 已是悬崖百丈冰, 15 # 犹有花枝俏。 16 # 17 # 俏也不争春, 18 # 只把春来报。 19 # 待到山花烂漫时, 20 # 她在丛中笑。 21 22 # 方法2:用join链接字符串的方式 23 f = open("咏梅", "rt", encoding="utf-8") 24 number = 0 25 for i in f.readlines(): 26 number += 1 27 if number == 2: 28 i = "".join([i.strip(), " 你回答的很正确"]) # 取代万恶的加号,字符串拼接 29 print(i.strip()) 30 # 显示结果: 31 # 风雨送春归, 32 # 作者:毛主席 你回答的很正确 33 # 飞雪迎春到。 34 # 已是悬崖百丈冰, 35 # 犹有花枝俏。 36 # 37 # 俏也不争春, 38 # 只把春来报。 39 # 待到山花烂漫时, 40 # 她在丛中笑。
3. 文件操作的其他几个内建函数
函:f.tell
语:f.tell(n)
用:检测光标(指针)当前的位置。注意:tell中文对应的光标和英文对应的光标占用位不一样(中文一般2个字符,英文一般一个字符)
函:f.seek
语:f.seek(n)
用:调整或移动光标(指针)当前的位置。注意seek和tell是意义对应的关系。通过seek调整光标的位置。起始位为:0
举例如下:
1 # tell(n) 2 # 作用:检测光标(指针)当前的位置 3 # 注意:tell中文对应的光标和英文对应的光标显示位置不一样 4 f = open("咏梅", "rt", encoding="utf-8") 5 print(f.tell()) # 刚开始光标在0的位置 6 print(f.read(4)) 7 print(f.tell()) # read了5个位置光标移动到12,中文占三个字符,英文是1个字符 8 # 显示结果: 9 # 0 10 # 风雨送春 中文字符占2个位。 11 # 12 现在光标到12的位置。 12 13 # seek(n) 14 # 作用:调整光标(指针)当前的位置 15 # 注意 seek和tell是一一对应的关系。通过seek调整光标的位置。 16 f = open("咏梅", "rt", encoding="utf-8") 17 print(f.read(1)) 18 print(f.read(2)) 19 print(f.read(3)) 20 f.seek(0) # 重新调整光标位置到第一个,重新读 21 print(f.read(1)) 22 # 显示结果: 23 # 风 开始读取一个中文字 24 # 雨送 然后再继续读两个中文字 25 # 春归,然后再继续读3个中文字(含1个字符) 26 # 风 # 回复到第一的位置
函:flush
语:f.flush()
用:这个函数的作用是把缓存里面的数据转存到硬盘里面(一般用于进度条制作)。方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要被动的等待输出缓冲区写入。一般情况下,文件关闭后会自动刷新缓冲区,但是有时候你需要在关闭前刷新他,这时就可以用f.flush的方法。注意:可以理解为:平时都是执行完一段代码滞后才能看见。用这个方法,可以边看边执行。
举例代码如下:
1 f = open("helloworld", "w") 2 f.write("Thomas is 35") 3 print(f.name) 4 f.write('hello ') # 执行一条 5 f.flush() # 刷新到文件中一条 6 f.write('world ') # 执行一条 7 f.close() # 刷新到文件中一条 8 # 文件中显示的结果: 9 # Thomas is 35hello 10 # world 11 12 import sys,time 13 f = open("hello001", "w", encoding="utf-8") 14 f.write("hello") 15 for i in range(10): 16 sys.stdout.write("*") 17 sys.stdout.flush() 18 time.sleep(0.5) # 按照0.5秒的速度刷新 19 # 显示内容: 20 # ********** 21 # Process finished with exit code 0
分析知识点:这里运用了库文件sys和time,这个后面会讲到。
函:truncate
语:truncate(n)
用:截断功能、默认是光标从第一个位置开始全部删除。如果设定参数设定,可以从设定的位置后面的所有内容都给截断。注意:这里打开文件的内容不能用w模式,因为w模式本身先进行一遍truncate过程。所以再用truncate会出错的。括号当中的n为从第几个字符进行截断,这里的中文字符再truncate函数中为3个字符为一个汉字。默认是从0开始,等同于w模式。
举例如下:
1 # truncate() 函数 2 # 作用:截断功能、默认是光标是从第一个位置开始全部删除。如果设定参数设定,可以从设定的位置 3 # 后面的所有内容都给接触 4 # 注意:这里打开文件模式不能用w模式。w本身要先进行一遍truncate过程。所以再用truncate会出错。 5 # 原文章: 6 # 风雨送春归, 7 # 飞雪迎春到。 8 # 已是悬崖百丈冰, 9 # 犹有花枝俏。 10 # 11 # 俏也不争春, 12 # 只把春来报。 13 # 待到山花烂漫时, 14 # 她在丛中笑。 15 f = open("咏梅", "a", encoding="utf-8") 16 f.truncate(3) 17 f.close() 18 # 显示结果: 19 # 风
4. 文件的修改问题
针对上面的内容,如果对一个文件进行修改是比较麻烦的,其实可以通过重写一份的方式进行文件的修改,类似于深拷贝的形式。很像一遍拿着课本,抄一遍,然后把要修改的地方记录下来。
举例代码:
1 # 文件的修改问题 # 2 # 把一整行进行替换 3 f_read = open("咏梅", "r", encoding="utf-8") 4 f_write = open("咏梅2", "w", encoding="utf-8") 5 6 number = 0 7 for line in f_read: 8 number += 1 9 if number == 5: 10 line = "hello 毛主席 " # 这样把第五行进行替换了 11 f_write.write(line) 12 f_write.close() 13 f_read.close() 14 # 显示结果: 15 # 风雨送春归, 16 # 飞雪迎春到。 17 # 已是悬崖百丈冰, 18 # 犹有花枝俏。 19 # hello 毛主席 20 # 俏也不争春, 21 # 只把春来报。 22 # 待到山花烂漫时, 23 # 她在丛中笑。 24 25 # 在一段后面添加字符串 26 f_read = open("咏梅", "r", encoding="utf-8") 27 f_write = open("咏梅2", "w", encoding="utf-8") 28 29 number = 0 30 for line in f_read: 31 number += 1 32 if number == 5: 33 line = "".join([line.strip(), "hello 毛主席 "]) 34 # line = "hello 毛主席 " # 这样把第五行进行替换了 35 f_write.write(line) 36 f_write.close() 37 f_read.close() 38 # 显示结果: 39 # 风雨送春归, 40 # 飞雪迎春到。 41 # 已是悬崖百丈冰, 42 # 犹有花枝俏。 43 # hello 毛主席 44 # 俏也不争春, 45 # 只把春来报。 46 # 待到山花烂漫时, 47 # 她在丛中笑。
5. 一个重要的知识点 with... as ...在文件操作中的应用
为了避免打开文件后忘记关闭,可以通过with语句管理上下文。with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源。比如文件使用后自动关闭、线程中的会自动获取和释放等。而且用with... as...的方式还可以同时打开多个文件。
语法:with context_expression [as target(s)]:
with_body
1 # with 2 # 作用:为了避免打开文件后忘记关闭,可以通过with语句管理上下文。 3 # with 语句适用于对资源进行访问的场合,确保不管使用过程中是否 4 # 发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、 5 # 线程中锁的自动获取和释放等。 6 # 语法: 7 # with context_expression [as target(s)]: 8 # with-body 9 with open("咏梅", "r", encoding="utf-8") as f: 10 f.readline() 11 f.read() 12 print("成功打开") 13 # 显示结果:成功打开 14 15 16 # 同样with语句在python3当中可以打开多个文件 17 with open("咏梅", "r", encoding="utf-8") as f, open("咏梅2", "w", encoding= 18 "utf-8") as f_write: 19 for i in f.readlines(): 20 print(i.strip()) 21 # 显示结果: 22 # 风雨送春归, 23 # 飞雪迎春到。 24 # 已是悬崖百丈冰, 25 # 犹有花枝俏。 26 # 27 # 俏也不争春, 28 # 只把春来报。 29 # 待到山花烂漫时, 30 # 她在丛中笑。
6. 其他补充
记得在标准化输入输出当中,print函数中有个参数为file = file.name。其实我们也可以通过print的函数来替代f.write函数把想要写的内容,打印到文件中。但是要注意的是,必须先要建立文件。
举例如下:
1 with open("李白", "w", encoding="utf-8") as f: 2 print("长风破浪会有时,直挂云帆济沧海", file=f) 3 # 文件中的显示结果: 4 # 长风破浪会有时,直挂云帆济沧海 # 是不是也是一样呢?
总结:
关于文件的操作,这里是基本操作,还有一些csv,png(图片),mp4(图像),wmv(声音)等高级文件操作方式,后面会有相关专题来进行讲解。