在平时,我们不光要对程序内的代码进行输入和输出的操作,还要对程序外的文件进行和语言之间的交换、操作和运算。在基础部分,先讲解对于外部的.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()

      用:获得当前函数句柄的编号。

 f = open("咏梅", "r", encoding="utf-8")
fno = f.fileno()
print(fno)
# print(f.fileno()) # 也可以直接打印观察
# 输出结果:3 f1 = open("咏梅", "r", encoding="utf-8")
fno1 = f1.fileno()
print(fno1)
# print(f1.fileno()) # 也可以直接打印观察
# 输出结果: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,\n、\r、"、'\r\n',用于区分换行符,但是这个参数只对文本有效。

  (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   一个最简单的操作并读取文件的过程。

  代码如下:

 # 一个简单的打开和操作 #
# 第一种打开方式:"r":只读模式
data = open("咏梅", "r", encoding="utf-8").read()
print(data)
print(type(data), "\n")
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。
# <class 'str'> # 第二种打开方式:采用函数句柄的方式打开文件。"r":只读模式
f = open("咏梅", "r", encoding="utf-8")
data = f.read()
print(data)
print(type(data), "\n")
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。
# <class 'str'>

  分析知识点:

  (1) 第一种方式为用只读方式简单的打开了一个文件,采用面向对象类的访问方式.read()的方式打开文件。

  (2) 第二种方式,用open函数打开文件后,赋值到一个句柄f当中,后面的所有操作都是根据句柄f展开的。我们看到这两种方式效果一样,但是建议采用后者,逻辑更清晰。

  (3) open函数一种最常用的格式为open("文件名", "读取模式", “编码格式”),这个必须记住。

  (4) 在这里我们用到了f.read的函数,根据另外两个read函数进行演示,以第二种方式为例。

  代码如下:

 # 例子1:只读取前三个字符(英文1个单词一个字符,中文1个字两个字符)
# 方法一:
f = open("咏梅", "r", encoding="utf-8")
data = f.read(3)
print(data)
print(type(data))
# 输出结果:
# 风雨送
# <class 'str'> # 方法二:
f = open("咏梅", "r", encoding="utf-8")
data = f.readline(3)
print(data)
print(type(data))
# 输出结果:
# 风雨送
# <class 'str'> # 例子2:用列表形式读取所有的内容
f = open("咏梅", "r", encoding="utf-8")
data = f.readlines()
print(data)
print(type(data))
# 输出结果:
# ['风雨送春归,\n', '飞雪迎春到。\n', '已是悬崖百丈冰,\n', '犹有花枝俏。\n', '\n', '俏也不争春,\n', '只把春来报。\n', '待到山花烂漫时,\n', '她在丛中笑。']
# <class 'list'> # 例子3:用列表的形式只读取前两行内容
f = open("咏梅", "r", encoding="utf-8")
data = f.readlines()
print(data[0:2])
print(type(data))
# 输出结果:
# ['风雨送春归,\n', '飞雪迎春到。\n']
# <class 'list'> # 例子4:用列表的形式只读取前两行内容,并把内容转换成字符串形式。
f = open("咏梅", "r", encoding="utf-8")
data = f.readlines()
data1 = data[0]
data2 = data[1]
data3 = data1 + data2
print(str(data3))
print(type(data3))
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
#
# <class 'str'>

  分析知识点

  (1) 从f.readlines和f.readline函数中我们可以看到f.readlines这个函数返回的结果是list(列表)类型,然后再通过查找列表的第几个元素,就是对应的第几行。

  (2) python对于选取行数的方式用转移成list的方式进行实习,通过list的下标再找到第几行

3.2    借用上面的例子,把读取的文件在最后光标位添加内容

  代码如下:

 # 例子1:在咏梅这首诗光标最后位置添加一段内容。
f = open("咏梅", "a+", encoding="utf-8")
data = f.write("大将生来胆气寒")
f.seek(0) # 这个函数下面会讲
data1 = f.read() # 这个时候文件指针放到最后一个字符,要用seek恢复指针。
print(data1)
f.close()
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。大将生来胆气寒 # 在结尾出添加了一句话。 # 例子2:在结尾处的下一行添加一段内容。
f = open("咏梅", "a+", encoding="utf-8")
data = f.write("\n大将生来胆气寒") # 在开始添加一个换行符
f.seek(0) # 这个函数下面会讲
data1 = f.read() # 这个时候文件指针放到最后一个字符,要用seek恢复指针。
print(data1)
f.close()
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。
# 大将生来胆气寒 # 添加在这里 # 例子3:观察打开的文件是否可写,如果可写用f.writelines的方式添加另外一首诗进去。
# 然后判断句柄是否可读,如果可读把文章读出来。
f = open("咏梅", "a+", encoding="utf-8")
if f.writable() == True: # 判断文章是否可写
list = ["\n锄禾日当午,", "\n汗滴禾下土。", "\n谁知盘中餐,", "\n粒粒皆辛苦。"]
f.writelines(list)
f.seek(0)
if f.readable() == True: # 判断文章是否可读
data = f.read()
print(data)
f.close()
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。
#
# 锄禾日当午,
# 汗滴禾下土。
# 谁知盘中餐,
# 粒粒皆辛苦。

  分析知识点:

  (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码的解码方式,肯定是个错误,如果错误的话,分别对应这三种结果会产生什么效果。

  代码如下:

 # errors
# 使用strict 严格方式。
f = open("咏梅", "r", errors="strict", encoding="ASCII")
data = f.read()
print(data)
# 输出结果:
# 产生一个报错,不应是用ASCII码来进行解码
# Traceback (most recent call last):
# File "C:/Users/Administrator/Desktop/Python-1704/day5/文件操作.py", line 221, in <module>
# data = f.read()
# File "F:\Users\Administrator\PycharmProjects\untitled\venv\lib\encodings\ascii.py", line 26, in decode
# return codecs.ascii_decode(input, self.errors)[0]
# UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128) # 使用 ignore 忽略方式。
f = open("咏梅", "r", errors="ignore", encoding="ASCII")
data = f.read()
print(data)
# 输出结果:
# 啥都没有显示,这个解码错误被忽略了。 # 使用 replace 替换方式。
f = open("咏梅", "r", errors="replace", encoding="ASCII")
data = f.read()
print(data)
# 输出结果:
# 一堆问号,错误解码用?来替代
# ������������������
# ������������������
# ������������������������
# ������������������
#
# ������������������
# ������������������
# ������������������������
# ������������������

  newline:

  newline是用来控制文本模式之下一行的结束字符。可以是None,'  ',\n,\r,\r\n等。在当读取模式下,如果新行符为None,那么就作为通用换行符模式工作,一是是说当遇到\n,\r  或者\r\n都可以作为换行标识,并统一转换为\n作为文本输入换行符。当设置为空'  ' 时,也就是通用换行符模式工作,但不作转换为\n,输入什么样,就保持原样全输入。当设置为其他相应字符时,就会判断到相应的字符作为换行符,并保持原样输入到文本。

  当输出模式时,如果新行符为None,那么所有输出文本都是采用\n作为换行符。如果设置为'  '空或者\n时,不做任何替换动作。如果是其他字符,会出现在字符后面添加\n作为换行符。

  这个功能也是不太常用的,而且python3中,只能用f.readlines进行演示演示代码如下:

 # 如果默认None状态
f = open("咏梅", "r+", encoding="utf-8", newline=None)
data = f.readlines()
print(data)
# 输出结果:正常显示
# ['风雨送春归,\n', '飞雪迎春到。\n', '已是悬崖百丈冰,\n', '犹有花枝俏。\n', '\n', '俏也不争春,\n', '只把春来报。\n', '待到山花烂漫时,\n', '她在丛中笑。\n'] # 如果"\r"的状态
f = open("咏梅", "r+", encoding="utf-8", newline="\r")
data = f.readlines()
print(data)
# 输出结果:用\r替代换行符\n,而\n提到前面去了。
# ['风雨送春归,\r', '\n飞雪迎春到。\r', '\n已是悬崖百丈冰,\r', '\n犹有花枝俏。\r', '\n\r', '\n俏也不争春,\r', '\n只把春来报。\r', '\n待到山花烂漫时,\r', '\n她在丛中笑。\r', '\n'] # 如果"\n"的状态
f = open("咏梅", "r+", encoding="utf-8", newline="\n")
data = f.readlines()
print(data)
# 输出结果:\r\n都表示换行
# ['风雨送春归,\r\n', '飞雪迎春到。\r\n', '已是悬崖百丈冰,\r\n', '犹有花枝俏。\r\n', '\r\n', '俏也不争春,\r\n', '只把春来报。\r\n', '待到山花烂漫时,\r\n', '她在丛中笑。\r\n'] # 如果"\r\n"的状态
f = open("咏梅", "r+", encoding="utf-8", newline="\r\n")
data = f.readlines()
print(data)
# 输出结果:\r\n都表示换行跟上面一样
# ['风雨送春归,\r\n', '飞雪迎春到。\r\n', '已是悬崖百丈冰,\r\n', '犹有花枝俏。\r\n', '\r\n', '俏也不争春,\r\n', '只把春来报。\r\n', '待到山花烂漫时,\r\n', '她在丛中笑。\r\n'] # 如果""的状态
f = open("咏梅", "r+", encoding="utf-8", newline="")
data = f.readlines()
print(data)
# 输出结果:与上面一个一样。
# ['风雨送春归,\r\n', '飞雪迎春到。\r\n', '已是悬崖百丈冰,\r\n', '犹有花枝俏。\r\n', '\r\n', '俏也不争春,\r\n', '只把春来报。\r\n', '待到山花烂漫时,\r\n', '她在丛中笑。\r\n']

  

  closefd:

  是否关闭,用来给当一个文件句柄传进来时,而当退出文件使用时,而不对文件句柄进行关闭。如果传递一个文件名进来,这个参数无效,必定为True方式。

  如果为True时:传入的file参数为文件的文件名

  如果为False时:传入的file参数只能是文件描述符。

  如果Ps:文件描述,就是一个非负整数,在Unix内核的系统中,打开一个文件,变回返回一个文件描述。

4.    剩下一点儿就是对于mode的模式几种进行一下说明

4.1   基本模式:

  "r"----只读模式,代码如下:

 # 只读模式
f = open("咏梅", "r", encoding="utf-8")
data = f.read()
print(data)
f.close()
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。

  分析知识点:没啥可说的,也就是打开文件只能读

  "w"----只写模式

 # 只写模式
f = open("二进制文件.txt", "w", encoding="utf-8")
data = f.read()
print(data)
f.close()
# 输出结果:
# Traceback (most recent call last):
# File "C:/Users/Administrator/Desktop/Python-1704/day5/文件操作.py", line 308, in <module>
# data = f.read()
# io.UnsupportedOperation: not readable

  分析知识点

  (1) 如果原文件不存在,文件名作为新建文件名且创建一个新的文件。

  (2) 如果源文件存在,会把原文件的内容全部覆盖掉,作为一个空文件以供添加内容。

  (3) 由于是只写模式,所以下面输出结果会报错。

  "a"----追加模式

 # 追加模式
f = open("咏梅", "a", encoding="utf-8")
data = f.write("作者:毛主席")
print(data)
f.close()
# 输出模式:
#
# 文件中显示:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。("a"模式打开后,指针位与这个位置)作者:毛主席

  分析知识点:注意一点"a"模式,指针开始会停留在最后一个字符的后面,也就是说,不添加换行等命令。是在最后一个位置进行添加。

  "U" ---- 通用换行符模式打开,---也就是rU简写是r等。

  "t" ---- 以文本模式打开(缺省模式)----也就是rt简写是r, wt简写是w,这个字符可以省略

  "b" ---- 二进制模式如下:

  "rb" ---- 读取二进制文件:

  "wb" --- 写二进制文件:

  "ab" ---- 追加二进制文件:

 # rb模式
f = open("咏梅", "rb")
# f.read()
data = f.read()
print(data)
#print(f) # 直接打印句柄,会显示描述文件<_io.BufferedReader name='咏梅'>
# print(f.read()) # 这样还直接打印不了,显示为:b''
f.close()
# 输出结果:
# b'\xe9\xa3\x8e\xe9\x9b\xa8\xe9\x80\x81\xe6\x98\xa5\xe5\xbd\x92\xef\xbc\x8c\r\n\xe9\xa3\x9e\xe9\x9b\xaa\xe8\xbf\x8e\xe6\x98\xa5\xe5\x88\xb0\xe3\x80\x82\r\n\xe5\xb7\xb2\xe6\x98\xaf\xe6\x82\xac\xe5\xb4\x96\xe7\x99\xbe\xe4\xb8\x88\xe5\x86\xb0\xef\xbc\x8c\r\n\xe7\x8a\xb9\xe6\x9c\x89\xe8\x8a\xb1\xe6\x9e\x9d\xe4\xbf\x8f\xe3\x80\x82\r\n\r\n\xe4\xbf\x8f\xe4\xb9\x9f\xe4\xb8\x8d\xe4\xba\x89\xe6\x98\xa5\xef\xbc\x8c\r\n\xe5\x8f\xaa\xe6\x8a\x8a\xe6\x98\xa5\xe6\x9d\xa5\xe6\x8a\xa5\xe3\x80\x82\r\n\xe5\xbe\x85\xe5\x88\xb0\xe5\xb1\xb1\xe8\x8a\xb1\xe7\x83\x82\xe6\xbc\xab\xe6\x97\xb6\xef\xbc\x8c\r\n\xe5\xa5\xb9\xe5\x9c\xa8\xe4\xb8\x9b\xe4\xb8\xad\xe7\xac\x91\xe3\x80\x82'
# 一连串的二进制地址位。 # wb模式
f = open("二进制文件", "wb")
f.write(b'\xe9\xa3\x8e\xe9\x9b\xa8')
f.close()
# 文本中的输出结果:
# 风雨 这两个汉字 # ab模板
f = open("二进制文件", "ab")
f.write(b"\xe9\x80\x81\xe6\x98\xa5")
f.close()
# 文本中的输出结果:
# 风雨送春 在风雨的后面又追加两个汉字

  分析知识点

  (1) 从这三个例子可以看出,二进制的输入要用二进制地址格式进行输入,像b"地址"  或者 b'地址' 这样才能去写,写到文本中后,会自动变为字符。

  (2) 二进制读取读取出来的也是像b"地址"  或者 b'地址'这样的二进制地址位。

  (3) 如果在某一个模式下,直接print(f)句柄,会得到os.BufferedReader缓冲区对于文件的简要描述

  (4) 如果直接打印print(f.write())这样的句柄模式,会得到输入了多少个字符。如果打印print(f.read())会全部内容。

  "+" ---- 加模式如下

  "r+"---- 读写/写读模式,先读后写

 # r+模式 两种变化
# 第一种:先写后读,指针从0行0位开始进行写,之前写的不动,会根据添加的字符进行不断的覆盖。
f = open("二进制文件", "r+", encoding="utf-8")
f.write("作者:毛主席\n作者:毛主席\n")
print(f.read())
f.close()
# 文本显示结果:
# 作者:毛主席 # 把前两行覆盖了
# 作者:毛主席
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。 # 第二种:先读后写,指针从0行0位读到最后一个字符的后, 这个时候写的话,变成追加模式了。
f = open("二进制文件", "r+", encoding="utf-8")
print(f.read())
f.write("作者:毛主席")
f.close()
# 文本显示结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。作者:毛主席 # 此时指针读完,放到最后,进行追加了。

  分析知识点

  (1) r+模式是r + w 模式的组合。

  (2) r+模式注意指针的变化

  "w+"---- 写读/读写模式

 # w+ 模式
f = open("二进制文件", "w+", encoding="utf-8")
f.write("作者:毛主席")
f.close()
# 文本中显示结果:
# 作者:毛主席

  分析知识点

  (1) w+模式是w + r 模式的组合。

  (2) w+模式注意指针的变化

  "a+"---- 追读/读追模式

 # a+ 模式
f = open("二进制文件", "a+", encoding="utf-8")
str = ["\n风雨送春归,", "\n飞雪迎春到"]
f.writelines(str)
f.close()
# 文本中显示结果:
# 作者:主席
# 风雨送春归,
# 飞雪迎春到

  分析知识点

  (1) a+模式是a + r 模式的组合。

  (2) a+模式注意指针的变化

第三部分 其他文件的操作方法

 1.   遍历打印方式

  之前我们知道用f.readlines()是输出了一个列表的形式,我们前面的代码访问具体的内容是用下标的方式,其实我们也可以用for遍历的方式也是一样的。

  用简单for循环的方式进行遍历,代码如下:

 # 遍历的方式打印所有的行
f = open("咏梅", "rt", encoding="utf-8")
for i in f.readlines():
print(i.strip()) # 如果不加strip,会多换一行,一般要加上一个strip()保持和原先文章一致
# 输出结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。

  用列表的方式进行遍历,代码如下:

 # 用列表的方式 进行遍历
f = open("咏梅", "rt", encoding="utf-8")
f = f.readlines()
num = 0
while num < len(f):
print(f[num].strip())
num += 1

  用枚举的方式进行遍历,代码如下:

 # 用枚举的方式进行遍历
f = open("咏梅", "rt", encoding="utf-8")
for i, v in enumerate(f.readlines(), 1): # 这是for 内部将f对象做成一个迭代器,用一行取一行
print(i, v.strip())
print(type(i))
print(i) # 迭代到最后一行
# 显示结果:
# 1 风雨送春归,
# 2 作者:毛主席
# 3 飞雪迎春到。
# 4 已是悬崖百丈冰,
# 5 犹有花枝俏。
#
# 7 俏也不争春,
# 8 只把春来报。
# 9 待到山花烂漫时,
# 10 她在丛中笑。
# <class 'int'>
#

  分析知识点:在这里遍历打印的时候i.strip()是常用的一种技巧,目的是为了在strip前后无效的\n\t这些位置去除掉。

2.   我们把咏梅的诗歌,第二行显示“作者:毛主席”,然后把第二行的毛主席显示一个字符串,用两种方式:

  代码如下:

 # 方法一:传统方法
f = open("咏梅", "rt", encoding="utf-8")
num = 0
for i in f.readlines():
num += 1
if num == 2: # 如果读到第二行
print(i.strip(), end=" 你回答的很正确")
else:
print(i.strip())
f.close()
# 显示结果:
# 风雨送春归,
# 作者:毛主席 你回答的很正确飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。 # 方法2:用join链接字符串的方式
f = open("咏梅", "rt", encoding="utf-8")
number = 0
for i in f.readlines():
number += 1
if number == 2:
i = "".join([i.strip(), " 你回答的很正确"]) # 取代万恶的加号,字符串拼接
print(i.strip())
# 显示结果:
# 风雨送春归,
# 作者:毛主席 你回答的很正确
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。

3.   文件操作的其他几个内建函数

  函:f.tell

    语:f.tell(n)

      用:检测光标(指针)当前的位置。注意:tell中文对应的光标和英文对应的光标占用位不一样(中文一般2个字符,英文一般一个字符)

  函:f.seek

    语:f.seek(n)

      用:调整或移动光标(指针)当前的位置。注意seek和tell是意义对应的关系。通过seek调整光标的位置。起始位为:0

  举例如下:

 # tell(n)
# 作用:检测光标(指针)当前的位置
# 注意:tell中文对应的光标和英文对应的光标显示位置不一样
f = open("咏梅", "rt", encoding="utf-8")
print(f.tell()) # 刚开始光标在0的位置
print(f.read(4))
print(f.tell()) # read了5个位置光标移动到12,中文占三个字符,英文是1个字符
# 显示结果:
#
# 风雨送春 中文字符占2个位。
# 12 现在光标到12的位置。 # seek(n)
# 作用:调整光标(指针)当前的位置
# 注意 seek和tell是一一对应的关系。通过seek调整光标的位置。
f = open("咏梅", "rt", encoding="utf-8")
print(f.read(1))
print(f.read(2))
print(f.read(3))
f.seek(0) # 重新调整光标位置到第一个,重新读
print(f.read(1))
# 显示结果:
# 风 开始读取一个中文字
# 雨送 然后再继续读两个中文字
# 春归,然后再继续读3个中文字(含1个字符)
# 风 # 回复到第一的位置

  函:flush

    语:f.flush()

      用:这个函数的作用是把缓存里面的数据转存到硬盘里面(一般用于进度条制作)。方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要被动的等待输出缓冲区写入。一般情况下,文件关闭后会自动刷新缓冲区,但是有时候你需要在关闭前刷新他,这时就可以用f.flush的方法。注意:可以理解为:平时都是执行完一段代码滞后才能看见。用这个方法,可以边看边执行。

  举例代码如下:

 f = open("helloworld", "w")
f.write("Thomas is 35")
print(f.name)
f.write('hello \n') # 执行一条
f.flush() # 刷新到文件中一条
f.write('world\n') # 执行一条
f.close() # 刷新到文件中一条
# 文件中显示的结果:
# Thomas is 35hello
# world import sys,time
f = open("hello001", "w", encoding="utf-8")
f.write("hello")
for i in range(10):
sys.stdout.write("*")
sys.stdout.flush()
time.sleep(0.5) # 按照0.5秒的速度刷新
# 显示内容:
# **********
# Process finished with exit code 0

  分析知识点:这里运用了库文件sys和time,这个后面会讲到。

  函:truncate

    语:truncate(n)

      用:截断功能、默认是光标从第一个位置开始全部删除。如果设定参数设定,可以从设定的位置后面的所有内容都给截断。注意:这里打开文件的内容不能用w模式,因为w模式本身先进行一遍truncate过程。所以再用truncate会出错的。括号当中的n为从第几个字符进行截断,这里的中文字符再truncate函数中为3个字符为一个汉字。默认是从0开始,等同于w模式。

  举例如下:

 # truncate() 函数
# 作用:截断功能、默认是光标是从第一个位置开始全部删除。如果设定参数设定,可以从设定的位置
# 后面的所有内容都给接触
# 注意:这里打开文件模式不能用w模式。w本身要先进行一遍truncate过程。所以再用truncate会出错。
# 原文章:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。
f = open("咏梅", "a", encoding="utf-8")
f.truncate(3)
f.close()
# 显示结果:
# 风

4.   文件的修改问题

  针对上面的内容,如果对一个文件进行修改是比较麻烦的,其实可以通过重写一份的方式进行文件的修改,类似于深拷贝的形式。很像一遍拿着课本,抄一遍,然后把要修改的地方记录下来。

  举例代码:

 # 文件的修改问题 #
# 把一整行进行替换
f_read = open("咏梅", "r", encoding="utf-8")
f_write = open("咏梅2", "w", encoding="utf-8") number = 0
for line in f_read:
number += 1
if number == 5:
line = "hello 毛主席\n" # 这样把第五行进行替换了
f_write.write(line)
f_write.close()
f_read.close()
# 显示结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
# hello 毛主席
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。 # 在一段后面添加字符串
f_read = open("咏梅", "r", encoding="utf-8")
f_write = open("咏梅2", "w", encoding="utf-8") number = 0
for line in f_read:
number += 1
if number == 5:
line = "".join([line.strip(), "hello 毛主席\n"])
# line = "hello 毛主席\n" # 这样把第五行进行替换了
f_write.write(line)
f_write.close()
f_read.close()
# 显示结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
# hello 毛主席
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。

5.   一个重要的知识点 with... as ...在文件操作中的应用

  为了避免打开文件后忘记关闭,可以通过with语句管理上下文。with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源。比如文件使用后自动关闭、线程中的会自动获取和释放等。而且用with... as...的方式还可以同时打开多个文件

  语法:with  context_expression  [as target(s)]:

        with_body

 # with
# 作用:为了避免打开文件后忘记关闭,可以通过with语句管理上下文。
# with 语句适用于对资源进行访问的场合,确保不管使用过程中是否
# 发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、
# 线程中锁的自动获取和释放等。
# 语法:
# with context_expression [as target(s)]:
# with-body
with open("咏梅", "r", encoding="utf-8") as f:
f.readline()
f.read()
print("成功打开")
# 显示结果:成功打开 # 同样with语句在python3当中可以打开多个文件
with open("咏梅", "r", encoding="utf-8") as f, open("咏梅2", "w", encoding=\
"utf-8") as f_write:
for i in f.readlines():
print(i.strip())
# 显示结果:
# 风雨送春归,
# 飞雪迎春到。
# 已是悬崖百丈冰,
# 犹有花枝俏。
#
# 俏也不争春,
# 只把春来报。
# 待到山花烂漫时,
# 她在丛中笑。

6.   其他补充

  记得在标准化输入输出当中,print函数中有个参数为file = file.name。其实我们也可以通过print的函数来替代f.write函数把想要写的内容,打印到文件中。但是要注意的是,必须先要建立文件。

  举例如下:

 with open("李白", "w", encoding="utf-8") as f:
print("长风破浪会有时,直挂云帆济沧海", file=f)
# 文件中的显示结果:
# 长风破浪会有时,直挂云帆济沧海 # 是不是也是一样呢?

总结

  关于文件的操作,这里是基本操作,还有一些csv,png(图片),mp4(图像),wmv(声音)等高级文件操作方式,后面会有相关专题来进行讲解。

 

Python笔记_第一篇_面向过程_第一部分_7.文件的操作(.txt)的更多相关文章

  1. Python笔记_第一篇_面向过程_第一部分_2.内存详解

    Python的很多教材中并没有讲内存方面的知识,但是内存的知识非常重要,对于计算机工作原理和方便理解编程语言是非常重要的,尤其是小白,因此需要把这一方面加上,能够更加深入的理解编程语言.这里引用了C语 ...

  2. Python笔记_第一篇_面向过程_第一部分_9.Ubuntu基础操作

    第一部分   Ubuntu简介 Ubuntu(乌班图)是一个机遇Debian的以桌面应用为主的Linux操作系统,据说其名称来自非洲南部祖鲁语或科萨语的“Ubuntu”一词,意思是“人性”.“我的存在 ...

  3. Python笔记_第一篇_面向过程_第一部分_6.其他控制语句(with...as等)

    其他控制语句,也就是说一个with... as...语句. 这是python非常精妙的一个语句,非常的简单但是作用非常大,在打开文件获得句柄的时候可以用它,省去f.close()忘记添加的麻烦(这个文 ...

  4. Python笔记_第二篇_面向过程_第二部分_2.路径、栈和队列、内存修改

    这一部分分三个主题进行讲解,主要为后面的模块.包.第三方库的概念补充一些相关的内容. 1. 路径(Path): 相对路径和绝对路径. 举例1:我们先导入一个os库(模块)来观察一下路径 import ...

  5. 四、java基础-面向过程_对象_类中可出现的因素

    1.面向过程和面向对象区别: 1)面向过程:开发一个应用程序.一个项目,必须先了解整个过程,了解各个步骤.模块间的因果关系,使的面向过程方式去开发程序时,代码和代码之间的关联程度是非常强.所以其中任何 ...

  6. python自动化开发-[第五天]-面向过程、模块、包

    今日概要: 1.内置模块 2.协程函数 3.递归 4.面向过程编程与函数编程 5.模块 6.包 7.re正则 一.内置模块 1.匿名函数lambda 定义:匿名函数通常是创建了可以被调用的函数,它返回 ...

  7. python第四周迭代器生成器序列化面向过程递归

      第一节装饰器复习和知识储备------------ 第一节装饰器复习和知识储备------------ def wrapper(*args,**kwargs): index(*args,**kwa ...

  8. [Python笔记]第八篇:模块

    本篇主要内容:python常用模块用法介绍 什么是模块 模块,用一大段代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性 ...

  9. [Python笔记]第三篇:深浅拷贝、函数

    本篇主要内容:深浅拷贝,自定义函数,三目运算,lambda表达式, 深浅拷贝 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import ...

随机推荐

  1. python_@classmethod

    class A(object): bar = 1 def func1(self): print ('foo') @classmethod def func2(cls): print ('func2') ...

  2. 【转载】使用driver.findElement(By.id("txtPhoneNum")).getText();获取文本

    今天在写自动化测试脚本的时候要获取一个输入框中的文本写了如下脚本: getAndSwitch("http://cas.minshengnet.com:14080/register/eRegi ...

  3. CSS实现背景图片透明和文字不透明效果

    1.毛玻璃效果:背景图 + 伪类 + flite:blur(3px) width: 500px; height: 300px; line-height: 50px; text-align: cente ...

  4. VM15上安装macOS操作系统

    (该篇博客已经成功安装上Xcode,放心下载) 因为要开学了,需要学习mac操作系统,自己没有苹果电脑只能虚拟机上下载喽 我在电脑上安装的VM15虚拟机,不会安装的可以来这里下载软件VM15虚拟机   ...

  5. [题解] CF438E The Child and Binary Tree

    CF438E The Child and Binary Tree Description 给一个大小为\(n\)的序列\(C\),保证\(C\)中每个元素各不相同,现在你要统计点权全在\(C\)中,且 ...

  6. springboot-jar-web

    预览 与springboot-jar的区别是: 1.pom.xml 将 <dependency> <groupId>org.springframework.boot</g ...

  7. 寒假day26

    根据已有数据爬取新数据充实人才库

  8. MyBatis:使用注解开发

    面向接口编程 大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大 ...

  9. Mac 用终端(命令行)打开vscode编辑器

    1.打开控制面板(⇧⌘P) 2.输入 shell command 在提示里看到 Shell Command: Install ‘code’ command in PATH, 就可以了. 3.使用: c ...

  10. POJ 3050:Hopscotch

    Hopscotch Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2506   Accepted: 1784 Descrip ...