open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数如下:
file:文件路径(绝对路径或者相对路径),如果直接写文件名的话那就是 相对路径
mode:为字符串参数,用于指定打开文件的模式,默认值是 “r”,也就是读取模式,其余模式参考下面内容
buffering:可选的整数参数,用于设置缓冲策略,若为 0 以切换缓冲关闭(仅允许在二进制模式下),1选择行缓冲(仅在文本模式下),大于1的整数以指示固定大小的块缓冲区的大小(单位:字节),如果没有给出参数,默认缓冲策略的工作方式如下:
encoding:指定用于解码或编码文件时 所 编码的名称,只在文本模式下使用,默认值(默认编码类型)是根据你的操作系统平台决定的,Windows系统是默认国产的 GBK编码,Liunx 、Macos 系统 为默认 UTF-8 编码,这也是为什么在Windos平台上打开utf-8编码文件时报错的原因,这里建议 好习惯 encoding=”utf-8"
errors:可选字符串参数,指定如何处理编码和解码错误,不能在二进制模式下使用
newline:控制 universal newlines (通用换行符)模式如何生效(它仅适用于文本模式),如果 newline 为 None,则启用通用换行模式,输入中的行可以以 ‘\n’,’\r’ 或 ‘\r\n’ 结尾,这些行被Python翻译成 ‘\n’ ,简单来说,就是以什么为判断内容下一行的依据,windos默认约定为 “\r\n” , Unix 为 “\n”,MacOS 为 “\r”
closefd:如果 closefd 是 False 并且给出了文件描述符而不是文件名,那么当文件关闭时,底层文件描述符将保持打开状态;如果给出文件名则 必须为 True(默认值,否则将引发错误
opener:设置自定义开启器,通过使用参数( file,flags )调用 opener 获得文件对象的基础文件描述符,开启器必须返回一个打开的文件描述符。
模式 | 描述 | 文件已存在 | 文件不存在 |
---|---|---|---|
r | 以 只读 方式打开文件(默认) | 正常读取 | 报错 FileNotFoundError |
rb | 以 二进制格式 打开文件 用于 读取 | 正常读取 | 报错 FileNotFoundError |
w | 以 只写 方式打开文件 | 清空原有内容从头开始写入 | 创建新文件进行写入 |
wb | 以 二进制 方式打开文件 用于 写入 | 清空原有内容从头开始写入 | 创建新文件进行写入 |
a | 以 追加 方式打开文件 | 新的内容将会被写入到已有内容末尾 | 创建新文件进行写入 |
ab | 以 二进制 方式打开文件 用于 追加 | 新的内容将会被写入到已有内容末尾 | 创建新文件进行写入 |
x | 排它性创建 写模式 | 创建新文件进行写入 | 报错 FileExistsError |
b | 不单独使用,二进制模式 | ~ | ~ |
t | 不单独使用,文本模式(默认) | ~ | ~ |
U | 通用换行模式(Python3 已弃用) | ~ | ~ |
以 内容数据 类型为参考的话,Python 区分二进制 和 文本,那么又分为文本模式 和 二进制模式
文本模式
在不指定文件模式时,默认模式为 “r”,打开用于读取文本,与 “rt” 是一样的。
文本模式下,文件内容返回为 字符串,使用 “r”,“w” 等模式时,与 后面加 “t” 相同,“r” = “rt”
二进制模式
二进制模式下,返回的内容为 bytes 对象,不进行任何解码
在Python 中创建 图片、视频等文件时,就需要用到 二进制模式 写入数据内容。
在使用 open() 内置函数 操作文件时,得记得在操作结束后加上一句 f.close()
每次操作完都得加上 f.close() ,显得有些麻烦,且如果在操作完忘记加上这一句话,还会造成资源一直占用的问题
于是,这里 推荐使用 with 语句 来提升编写代码的效率
普通写法
f = open("中文.txt", "r", encoding="utf-8")
data = f.read()
print(data)
f.close()
使用 with 语句
with open("中文.txt", "r", encoding="utf-8") as f:
data = f.read()
print(data)
优点:
接下来的代码,我将统一使用 with 语句演示
创建文件,常用的 文件打开模式是 “w”,当然也可以使用 “x” 模式,前提是你所指定的目录下没有这个文件
只是创建一个空白文件的话 可以这么写
with open("文件.txt", "w", encoding="utf-8") as f_w:
pass
创建多个文件 可以配合循环
for i in range(1, 5):
with open(f"文件_{i}.txt", "w", encoding="utf-8") as f_w:
pass
创建文件 并且 写入内容
with open(f"文件.txt", "w", encoding="utf-8") as f_w:
f_w.write("hello word")
读取文件,用到的 文件打开模式是 “r”
.read(size = -1)*
读取全部
读取全部内容
with open(f"中文.txt", "r", encoding="utf-8") as f_w:
data = f_w.read() # 读取所有内容
print(data)
利用 size 参数 在特点场合下有妙用
with open(f"中文.txt", "r", encoding="utf-8") as f_w:
while True:
data = f_w.read(10) # 每次只读取10个字节
if data:
print(data)
else:
break
.readline(size = -1)
读取一行
读取一行
with open(f"中文.txt", "r", encoding="utf-8") as f_w:
data = f_w.readline()
print(data)
一行一行方式读取 全部内容
with open(f"中文.txt", "r", encoding="utf-8") as f_w:
while True:
data = f_w.readline()
if not data:
break
print(data)
# 还可以直接循环文件对象实现
with open(f"中文.txt", "r", encoding="utf-8") as f_w:
for line in f_w:
print(line)
.readline(size = -1)
读取所有行,并返回列表,每一行为列表中的一个值
with open(f"中文.txt", "r", encoding="utf-8") as f_w:
data_list = f_w.readlines()
print(data_list)
对文件内容进行追加,用到的 文件打开模式是 “a”
追加的内容会写在文件末尾
with open("中文.txt", "w", encoding="utf-8") as f_w: # 创建初始文件
f_w.write("我是第一行内容\n")
with open("中文.txt", "a", encoding="utf-8") as f_a: # 追加文件内容
f_a.write("我是追加的内容")
这个模式用在写简单的 程序运行 日志 上
需要使用到两种 文件打开模式 进行配合,先读(“r”)后写(“w”)
原理:
很简单,就是先将 内容读取 到内存,然后对读取到的数据进行修改、增加、删除等操作,再重新写入到新文件中,再把旧文件替换成新文件,在编辑过程未结束的情况下 产生的新文件可以理解为 临时文件,此时尚未与旧文件替换
这种修改方式其实很常见,拿我们常用的 word 文档来看
在平时编辑word文档时,会发现在其相对路径下会生成一个隐藏文件,命名通常是以~$开头,后面跟着文件名
替换文件
那么,在py中怎么替换文件呢?
这就需要用到 os 标准库模块下的 os.replace()
os.replace("新文件", "旧文件")
根据以上原理,Py实现
temp_name = r"~$"
file_name = "中文.txt"
with open(f"{temp_name}{file_name}", "w", encoding="utf-8") as f_w:
with open(file_name, "r", encoding="utf-8") as f_r:
data = f_r.read()
data = data.replace("内容", "nei_rong") # 替换操作
data += "我是再加上的内容\n" # 增加内容
f_w.write(data)
os.replace(f"{temp_name}{file_name}", file_name) # 替换文件
这里需要用到 os 标准库模块
file_path = ""
if os.path.isfile(file_path):
os.remove(file_path) # 只能删除文件 非文件夹
注意:只能删除文件,非文件夹,否则会出现 OSError 错误
需要注意的是,文件夹分两种,一种是空文件夹,另外一种则是文件夹中有内容的 非空文件夹
dir_path = ""
if not os.listdir(dir_path):
os.rmdir(dir_path)
7 > 如果删除非空文件夹,会出现 OSError 错误
非空文件夹:
方法一:(推荐)
利用 shutil 标准库模块
shutil.rmtree() 删除一个完整的目录树
path = ""
if os.path.isdir(path):
shutil.rmtree(path) # 删除非空文件夹
方法二:
还是使用回 os 标准库模块中的功能,但这个方法比较繁琐
for b, d, f in os.walk(path, topdown=False): # 一定要设置 topdown 参数为False,从里层开始
for file_n in f:
os.remove(os.path.join(b, file_n))
for dir_p in d:
dir_p = os.path.join(b, dir_p)
if not os.listdir(dir_p):
os.rmdir(dir_p)
else:
os.rmdir(path)
OS 模块是个利器,操作文件时 有 OS 可以做出更厉害的操作
导入os模块
import os
判断文件是否存在
os.path.isfile() # 判断路径是否为文件
根据文件是否存在决定写入模式
file_path = "" # 文件目录
if os.path.isfile(file_path):
print("文件存在")
with open(file_path, "a", encoding="urf-8") as f_a:
f_a.write("写入内容") # 追加文件中的内容
else:
print("文件不存在")
with open(file_path, "w", encoding="utf-8") as f_w:
f_w.write("写入内容")
拼接路径
os.path.join() # 把目录和文件名合成一个路径
path = os.path.join("路径一", "路径二")
获取根路径
适用于当前所运行的 py文件
BASE_DIR = os.path.dirname(__file__) # 获取当前Py 根目录
判断文件夹是否存在
os.path.isdir() # 判断路径是否为目录
如果文件夹不存在,则创建文件夹并在此文件夹内创建文件
BASE_DIR = os.path.dirname(__file__) # 获取当前Py 根目录
dir_path = [os.path.join(BASE_DIR, "我是文件夹"), ] # 文件夹路径
file_path = os.path.join(dir_path[0], "我是文件.txt") # 文件目录
def judg_isdir(funx):
"""
文件夹初始化装饰器
"""
def inner(*args, **kwargs):
for d in dir_path:
if not os.path.isdir(d): # 如果文件夹不存在则创建
os.mkdir(d)
return funx(*args, **kwargs)
return inner
@judg_isdir
def mydir():
if os.path.isfile(file_path): # 如果文件存在
print("文件存在")
with open(file_path, "a", encoding="urf-8") as f_a:
f_a.write("写入内容") # 追加文件中的内容
else:
print("文件不存在")
with open(file_path, "w", encoding="utf-8") as f_w:
f_w.write("写入内容")
mydir()
ASCII
ASCII (American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁 字母 的一套编码,主要用于显示现代英语和其他西欧语言,是最通用的信息交换标准,并等同于国际标准 ISO/IEC 646
ASCII 第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符
由于计算机是美国人发明的,因此最早只有 ASCII 被编码到计算机里,大小写英文字母、数字和一些符号
大写字母 A 对应的编码是65,小写字母 a 对应编码是97,数字 1 对应的编码是 49
这些都可以通过 Python内置函数 ord() 进行查看
print(ord("A"))
print(ord("a"))
print(ord("1"))
GB2312 & GBK
GB2312 和 GBK 都为 国产编码,GB2312 于1980年 最早发布
GBK 是 GB2312 的升级版,加入更多字符,向下与 GB 2312 编码兼容国产编码,一直用到现在,Windos中文平台 默认编码依旧是 GBK
可以在 命令提示符 中的属性 看到Windos平台 默认的编码
Unicode
Unicode 是 ISO(国际标谁化组织)制定的可以容纳世界上所有文字和符号的字符编码,所以又俗称 万国码、统一码,解决了 传统的字符编码方案的局限(简单来说:每个国家都有自己一套的编码标准,如果跨国办公或者跨国产品,很容易出现各个国家编码不相通,造成乱码,在当时万国码没出来之前,各国之间的编码可谓是战国时期,乱码现象很常见)
特点:
Unicode 为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理、阅读,极大改善了不同国家之间的信息传递
可以跟各种语言的编码自由转换,兼容性很强,比如说用 gbk编码 的文本 ,可以转成Unicode
容纳世界上所有文字和符号的字符编码
UTF-8
Unicode 是 字符集,UTF-8 是 编码规则
UTF-8 就是 Unicode 的实现方式,对unicode字符集进行编码的一种编码方式
在计算机内存中,使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码
具体流程:编辑文本时,从文件读取 UTF-8 字符转换为 Unicode 字符到内存里,进行编辑操作,编辑完成后,再把内存中的 Unicode 字符 转换为UTF-8 字符 存储到文件里
注意:utf-8 不能直接于 gbk 转换,需要有 Unicode 作为中间人 过渡,这是为什么 在WIndows平台上 打开utf-8文本文件时容易出现乱码的原因
此外 还有UTF-16,UTF-32
对比表
依据 出现时间 排序
编码 | 出现时间 | 描述 | 所占大小 |
---|---|---|---|
ASCII | 1967年 | 最早诞生编码,英语和西欧语言 | 一字节 |
GB2312 | 1980年 | 国产简体中文编码,兼容 ASCII 码 | 两字节 |
Unicode | 1991年 | 国际统一标准字符集,俗称万国码 | 两字节 |
GBK | 1995年 | GB2312升级版,支持繁体,加入更多字符 | 两字节 |
UTF-8 | 1992年 | 不定长编码 | 1 - 3 字节 |