1.文件概念
计算机的文件,就是存储在某种 长期储存设备 上的一段 数据。
2.文件的存储方式
①文本文件
◦可以使用 文本编辑软件 查看
◦本质上还是二进制文件
例如:python 的源程序
②二进制文件
◦保存的内容 不是给人直接阅读的,而是 提供给其他软件使用的
◦例如:图片文件、音频文件、视频文件等等
◦二进制文件不能使用 文本编辑软件 查看
3.文件的基本操作
3.1打开文件
open()
用open函数打开文件。open()是python的内置函数,它会返回一个可迭代的文件对象,这个文件对象拥有read、readline、write、close等方法。
open函数有两个参数:open('file','mode')
- file:需要打开的文件路径+文件名,绝对路径或者当前工作目录的相对路径
- mode(可选):打开文件的模式,如只读、追加、写入等
第一个参数是要打开的文件名(文件名区分大小写)
◦如果文件存在,返回文件操作对象
◦如果文件不存在,会抛出异常
当将文件名传递给函数open()时,Python将在当前执行的文件(即.py程序文件)所在目录中查找文件。例如:open()打开文件,并且返回文件操作对象 ,python将这个对象存储在后面使用的变量file_object中。
#例如
with open('text_files\filename.txt') as file_object:
要让Python打开不与程序文件位于同一个目录中的文件,需要提供文件路径,它让python到系统的特定位置去查找。
绝对文件路径:
#例如
file_path = 'C:\Users\ehmattes\other_files\text_files\filename.txt'
with open(file_path) as file_object:
mode参数可以省略不填,默认为r模式。mode常用的模式:
- r:以只读方式打开文件,文件的指针将会放在文件的开头,这是默认模式;如果文件不存在,抛出异常 。
- w:以只写方式打开文件,如果文件存在会被覆盖;如果文件不存在,创建新文件 。
- a:表以附加方式打开文件,如果该文件已存在,文件指针将会放在文件的结尾;如果文件不存在,创建新文件进行写入。
- w+:表示可以对文件进行读写双重操作,如果文件存在会被覆盖;如果文件不存在,创建新文件 。
- r+ :以读写方式打开文件,文件的指针将会放在文件的开头;如果文件不存在,抛出异常 。
- a+ :以读写方式打开文件,如果该文件已存在,文件指针将会放在文件的结尾;如果文件不存在,创建新文件进行写入 。
当你需要以字节(二进制)形式读写文件时,只需要在mode参数中追加'b'即可:
- rb:以二进制格式打开一个文件,用于只读
- wb:以二进制格式打开一个文件,用于只写
- ab:以二进制格式打开一个文件,用于追加
- wb+:以二进制格式打开一个文件,用于读写
with关键字
在打开文件时,很多人通常直接用open('file'),这样并不酷,还很繁琐。最好使用 with
关键字。优点是当子句体结束后文件会正确关闭,即使在某个时刻引发了异常。
关键字with在不再需要访问文件后将其关闭;read()读取整个文件。
>>> with open('workfile') as f:
... read_data = f.read()
>>> f.closed
True
open() 方法完整的语法格式为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
- file: 必需,文件路径(相对或者绝对路径)。
- mode: 可选,文件打开模式
- buffering: 设置缓冲
- encoding: 一般使用utf8
- errors: 报错级别
- newline: 是用来控制文本模式之下,一行的结束字符。可以是None,’’,\n,\r,\r\n等。当在读取模式下,如果新行符为None,那么就作为通用换行符模式工作,意思就是说当遇到\n,\r或\r\n都可以作为换行标识,并且统一转换为\n作为文本输入的换行符。当设置为空’’时,也是通用换行符模式工作,但不作转换为\n,输入什么样的,就保持原样全输入。当设置为其它相应字符时,就会判断到相应的字符作为换行符,并保持原样输入到文本。当在输出模式时,如果新行符为None,那么所有输出文本都是采用\n作为换行符。如果设置为’’或者\n时,不作任何的替换动作。如果是其它字符,会在字符后面添加\n作为换行符。
- closefd: 传入的file参数类型
- opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符
详见https://www.cnblogs.com/SupremeBoy/p/12267967.html
file对象使用 open 函数来创建
1 | 关闭文件。关闭后文件不能再进行读写操作。 |
2 | 刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。 |
3 | 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。 |
4 | 如果文件连接到一个终端设备返回 True,否则返回 False。 |
5 | Python 3 中的 File 对象不支持 next() 方法。 返回文件下一行。 |
6 | 从文件读取指定的字节数,如果未给定或为负则读取所有。 |
7 | 读取整行,包括 "\n" 字符。 |
8 | 读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。 |
9 | 移动文件读取指针到指定位置 |
10 | 返回文件当前位置。 |
11 | 从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。 |
12 | 将字符串写入文件,返回的是写入的字符长度。 |
13 | 向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。 |
3.2从文件中读取数据
当使用open函数打开文件后,就可以使用该文件对象的各种方法了,read就是其中一种。
read()会读取一些数据并将其作为字符串(在文本模式下)或字节对象(在二进制模式下)返回。
读(read):将文件内容读进内存
read() 可以一次性读入并返回文件的所有内容,如果文件太大,对内存的占用会非常严重
readline 方法 •readline() 可以一次读取一行内容
•方法执行后,会把 文件指针 移动到下一行,准备再次读取
read 方法执行后,会把 文件指针 移动到 文件的末尾
# 也可以使用for循环以每次一行的方式检查文件
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
使用关键字with时,open()返回的文件对象只在with代码块内可使用,如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表。
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
read方法有一个参数:f.read(size) # f为文件对象
- 参数size(可选)为数字,表示从已打开文件中读取的字节计数,默认情况下为读取全部。
3.3写入文件
写(write):将内存内容写入文件
①写入空文件
filename = 'programming.txt'
with open(filename,'w') as file_object:
file_object.write("I love programming.")
②写入多行
write()不会在你写入的文本末尾添加换行符,因此要写入多行时需要指定换行符。
filename = 'programming.txt'
with open(filename,'w') as file_object:
file_object.write("I love programming.\n")
file_object.write("I love creating new games.\n")
③附加到文件
filename = 'programming.txt'
with open(filename,'a') as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
3.4关闭文件
close()负责关闭文件。
f.close() 用来关闭文件并立即释放它使用的所有系统资源。如果你没有显式地关闭文件,Python的垃圾回收器最终将销毁该对象并为你关闭打开的文件,但这个文件可能会保持打开状态一段时间。
应该要养成使用close()的习惯。
f = open(file) # 打开文件
f.close() # 关闭文件
但是,如果程序存在bug,导致close()语句未执行,文件将不会关闭,可能会导致数据丢失或受损。因此,可以让Python去确定,你只管打开文件,并在需要时使用它,Python会在合适的时候自动将其关闭(我们无需调用close())。
总结
open 函数负责打开文件,并且返回文件对象, read/write/close 三个方法都需要通过 文件对象 来调用
# 1. 打开 - 文件名需要注意大小写
file = open("README")
# 2. 读取
text = file.read()
print(text)
# 3. 关闭
file.close()
读取数据文件(txt、csv、xml、json)
①读取txt文件
- read():读取整个文件
- readline():读取一行数据
- readlines():读取所有行数据
- 另:write():将字符串写入到文件里, f.write([str]) # f为文件对象
举例:将用户名、密码按行写入txt文件中,用户名和密码之间用冒号“:”隔开。读取txt文件:
#读取文件,.表示统计目录,..表示上级目录
with open('../file/user.txt','r') as f:
data = f.readlines()
#格式化处理
users = []
for line in data:
#line[:-1]是为了去掉每一行后面的\n
user = line[:-1].split(":")
users.append(user)
#打印二维数组
print(users)
结果:[['', '123'], ['user', ''], ['error', 'error'], ['admin', 'admin12']]
也可改成绝对路径(注意是/而不是\):with open('F:/study/test_data/user.txt','r') as f 或者 with open(r'F:\study\test_data\user.txt','r') as f
②读取csv文件
csv模块:csv --- CSV 文件读写 — Python 3.12.0 文档
codecs模块:codecs --- 编解码器注册和相关基类 — Python 3.8.17 文档
itertools模块:itertools --- 为高效循环而创建迭代器的函数 — Python 3.8.17 文档
reader(csvfile, dialect='excel', **fmtparams) 返回一个 reader 对象,该对象将逐行遍历 csvfile。
- csvfile必须是支持迭代(Iterator)的对象,文件对象 和列表对象均适用。如果 csvfile 是文件对象,则打开它时应使用 newline='',(with open('eggs.csv', newline='') as csvfile:)
(如果是文件对象,打开时需要加"b"标志参数。比如:with open('test.csv','rb') as myFile:)这两种不确定是哪种...... - dialect,编码风格,默认为excel的风格,也就是用逗号(,)分隔,dialect 方式也支持自定义,有delimiter(分隔符,默认的就是逗号)、quotechar、quoting等等,可以参考Dialects and Formatting Parameters。
- fmtparam,格式化参数,用来覆盖之前dialect对象指定的编码风格。
codecs.open(filename, mode='r', encoding=None, errors='strict', buffering=-1)
- 使用给定的 mode 打开已编码的文件并返回一个 StreamReaderWriter 的实例,提供透明的编码/解码。 默认的文件模式为 'r',表示以读取模式打开文件。
- encoding 指定文件所要使用的编码格式。 允许任何编码为字节串或从字节串解码的编码格式,而文件方法所支持的数据类型则取决于所使用的编解码器。
- 可以指定 errors 来定义错误处理方案。 默认值 'strict' 表示在出现编码错误时引发 ValueError。
- buffering 的含义与内置 open() 函数中的相同。 默认值 -1 表示将使用默认的缓冲区大小。
itertools.
islice
(iterable, start, stop[, step]) 创建一个迭代器,返回从 iterable 里选中的元素
- start:指定开始迭代的位置
- 如果 stop 为
None
,迭代器耗光为止
CSV文件常会遇到的问题:
①中文乱码问题,解决:导入codecs,codecs是Python标准的模块编码和解码器,首先,通过codecs提供的open()方法,在打开文件时可以指定编码类型,如utf_8_sig,然后,通过csv模块的reader()方法读取文件,即可避免中文乱码问题。
②经常会在第一行定义测试字段名。解决:读取时跳过第一行。Python的内建模块itertools提供了用于操作迭代对象的函数,即islice()函数,它可以返回一个迭代器第一个参数指定迭代对象,第二个参数指定开始迭代的位置,第三个参数表示结束位。
import csv
import codecs
from itertools import islice
#读取本地CSV文件
data = csv.reader(codecs.open('F:/study/test_data/csv_test.csv','r','gb18030'))
#存放用户数据
users = []
#循环输出每行信息
for line in islice(data,1,None):
users.append(line)
#打印
print(users)
结果:[['user', '', '请输入密码'], ['', '123', '请输入账号'], ['error', 'error', '账号或密码错误'], ['admin', 'admin123', 'admin你好']]
③读取xml文件
python自带读取XML文件的模块,通过parse()方法可读取XML文件。
from xml.dom.minidom import parse
后续再补充
④读取json文件
import json
后续再补充
4.文件/目录的常用管理操作
•在 终端 / 文件浏览器、 中可以执行常规的 文件 / 目录 管理操作,例如: 创建、重命名、删除、改变路径、查看目录内容等等
•在 Python 中,如果希望通过程序实现上述功能,需要导入 os 模块
4.1文件操作
rename 重命名文件 例如: os.rename(源文件名, 目标文件名)
remove 删除文件 例如:os.remove(文件名)
4.2目录操作
listdir 目录列表 os.listdir(目录名)
mkdir 创建目录 os.mkdir(目录名)
rmdir 删除目录 os.rmdir(目录名)
getcwd 获取当前目录 os.getcwd()
chdir 修改工作目录 os.chdir(目标目录)
path.isdir 判断是否是文件 os.path.isdir(文件路径)
文件或者目录操作都支持 相对路径 和 绝对路径
5. 文本文件的编码格式
文本文件存储的内容是基于 字符编码 的文件,常见的编码有 ASCII 编码,UNICODE 编码等
Python 2.x 默认使用 ASCII 编码格式
Python 3.x 默认使用 UTF-8 编码格式
ASCII 编码
•计算机中只有 256 个 ASCII 字符
•一个 ASCII 在内存中占用 1 个字节 的空间
◦8 个 0/1 的排列组合方式一共有 256 种,也就是 2 ** 8
UTF-8 编码格式
•计算机中使用 1~6 个字节 来表示一个 UTF-8 字符,涵盖了 地球上几乎所有地区的文字
•大多数汉字会使用 3 个字节 表示
•UTF-8 是 UNICODE 编码的一种编码格式
6.跨目录调用文件
当我们导入一个模块时:import xxx,默认情况下python解析器会搜索当前目录、已安装的内置模块和第三方模块,搜索路径存放在sys模块的path中。
当我们要添加自己的搜索目录时,可以通过列表的append()方法,对于模块和自己写的脚本不在同一个目录下,在脚本开头加sys.path.append('xxx')
Python os.path() 模块Python os.path 模块 | 菜鸟教程
os.path.abspath(path) 返回绝对路径
os.path.dirname(path) 返回上级目录路径
__file__用于获取文件所在的路径,abspath(__file__)可以得到ccc.py文件的绝对路径:F:\study\springroad\runner\ccc.py
sys.path.append(path)中需要的路径为:要引用aaa.py文件所属的目录(F:\study\springroad\common)
所以,dirname(dirname(abspath(__file__)))两个dirname()函数嵌套使用时,可以得到上两级目录
project_path + "\\common"即得到F:\study\springroad\common
另:怎么编写自测代码:
if __name__ == '__main__':
#测试代码
if __name__ == '__main__'表示:当模块被直接运行时,下面的代码块将被允许,当模块被其他程序文件调用时,下面的代码块不被运行。