1、目的:是要将数据永久地保存下来,就需要将数据永久保存在硬盘中。
例如:从文件中读入信息,比如从日志文件中读入日志,从而分析数据信息。写入文本信息到文件中,比如写入操作信息到日志文件中。
2、概念:文件就是操作系统提供给应用程序来操作硬盘虚拟接口,用户或应用程序通过操作文件,可以将自己的数据永久地保存下来。
写入字符串到文件中,需要先将字符串编码为字节串。
而从文件中读取的文本信息都是字节串,要进行处理前,必须先将字节串解码为字符串。
3、步骤;
1)打开文件,得到一个文件句柄,并赋值给一个变量。
2)通过句柄对文件进行操作。
3)关闭文件。
4、Open函数:
首先通过内置函数open打开文件,获得一个文件对象。

其中有三个参数是我们比较关注的。
file参数、mode参数和encoding参数。
1)file参数:指定要打开文件的路径。有绝对路径和相对路径。
2)mode,指定了打开文件的模式。打开文件的模式,决定了怎样操作文件。
3)encoding 参数制定了读写文件时,使用的字符编解码的方式。

truncating 清空的意思。清空数据库的表也是这个单词。
| mode参数 | 解释 |
| r | 读(默认) |
| w | 写 |
| a | 在文件最后位置追加内容 |
| b | 二进制模式 |
| + | 以读和写的方式打开文件,便于更新文件 |
调用open函数时,如果传入了encoding参数值:
后面调用write写入字符串到文件中,open函数会使用指定encoding编码为字节串;
后面调用read从文件中读取内容,open函数会使用指定encoding解码为字符串对象;
总之,最后在磁盘中保存的是字符串的编码方式。
如果不指定encoding参数,open函数会使用系统设置的字符编码方式。
我们使用的windows系统,cp936(gpk编码方式。)
建议在编写代码 读写文本文件的时候,都指定该参数的值。
看几个例子:
- # 读模式,将log中内容一次性读出
- f = open('log', mode='r', encoding='utf-8')
- content = f.read()
- print(content)
- f.close()
-
- # 写方式,清空内容然后再写入
- f = open('log', mode='w', encoding='utf-8')
- f.write('abcdefg')
- f.close()
-
- # 在文件内容后追加写入
- f = open('log', mode='a', encoding='utf-8')
- f.write('abcdefg')
- f.close()

指定了编码方式,可以看到确实是utf8的编码方式。
说明:
打开一个文件包含两个部分的内容,操作系统级打开的文件和应用程序级的变量。在操作完毕一个文件时,必须把与该文件的相关的这两部分资源文件进行回收。对于操作系统打开的文件,使用f.close()进行回收,对于应用程序级的变量,应使用def f(Python有自动的垃圾回收机制,所以不需要考虑del f)。
建议使用with关键字来帮助管理上下文,系统会自动为我们关闭文件和处理异常。
- with open('log', mode='w', encoding='utf-8') as f:
- f.write('Hello, Python.')
编码:encoding=是我们为open指定编码,但如果我们没有指定,那么打开的文件默认编码就是操作系统设置的的编码:在windows下是GBK,在Linux下是UTF-8。为了保证不出现乱码,我们必须让读文件和写文件使用的编码一致。
IDE集成开发环境默认的是UTF8编码方式。
- # 指定编码方式为 gbk,gbk编码兼容gb2312
- f = open('tmp.txt', 'r', encoding='gbk')
-
- # read 方法会在读取文件中的原始字节串后, 根据上面指定的gbk解码为字符串对象返回
- content = f.read()
-
- # 文件操作完毕后, 使用close 方法关闭该文件对象
- f.close()
-
- # 通过字符串的split方法获取其中用户名部分
- name = content.split(':')[0]
-
- print(name)


read函数有参数size,读取文本文件的时候,用来指定这次读取多少个字符。 如果不传入该参数,就是读取文件中所有的内容。
有一个文件指针的概念,要掌握。就是类似光标的概念。f.seek() 按字节移动光标。
5、文件的操作方式:
| 方法名称 | 功能 |
| f.read() | 读取所有内容,以字符为最小单位。 |
| f.readline() | 读取一行内容 |
| f.readlines() | 读取每一行内容,存放在列表中 |
| f.write() | 写信息 |
| f.write(''1111\n2222\n'.encode('utf-8') | 针对b模式的写 |
| f.writelines() | 文件模式 |
| f.readable() | 判断文件是否可读 |
| f.writable() | 判断文件是否可写 |
| f.closed() | 文件是否关闭 |
| f.encoding | 如果文件打开模式是b,则没有该属性 |
| f.flush() | 立即将文件内容从内存刷到硬盘 |
| f.seek() | 按字节移动光标 |
| f.tell() | 读取光标位置 |
| f.truncate | 截取文件 |
例1: 基于seek实现类似Linux命令tail -f的功能。
- import time
-
- with open('log', mode='rb') as f:
- f.seek(0, 2)
- while True:
- line = f.read()
- if line:
- print(line.decode('utf-8'), end='')
- else:
- time.sleep(0.2)
当在log追加新的内容时,新内容就会被程序立即打印出来。
例2:修改文件。
- with open('log', encoding='utf-8') as read_f, open('log.bak', 'w', encoding='utf-8') as write_f:
- data = read_f.read() # 全部读入内存,建议文件不要太大
- data = data.replace('chang', 'wang') # 在内存中完成修改
-
- write_f.write(line) # 一次性写入新文件
-
- import os
- os.remove('log') # 将原文件进行删除
- os.rename('log.bak', 'log') # 将log.bak文件重命名为log
如果文件很大:
- with open('log', encoding='utf-8') as read_f, open('log.bak', 'w', encoding='utf-8') as write_f:
- for line in read_f:
- if 'chang' in line:
- line = line.replace('chang', 'wang')
-
- write_f.write(line)
-
- import os
- os.remove('log') # 将原文件进行删除
- os.rename('log.bak', 'log') # 将log.bak文件重命名为log
f.read适合读取小文件。