在Python项目中,文件读写是比较常见的操作,读写文件首先需要打开指定的文件,可以通过Python的内置函数open()实现。
1、open()函数打开文件
open()函数有许多参数,在Python官方文档中open()函数的定义如下所示:
file = open(file_name, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
在上面open()函数的参数中,只有第一个file_name参数是必须传递的,其它参数都有默认值,可以不用填写。第一个file_name参数是你要访问的文件路径。例如:
动手练一练:
filename = "test.py"
f = open(filename)
print(f)
执行以上代码,输出结果为:
<_io.TextIOWrapper name='test.py' mode='r' encoding='cp936'>
上面的例子中,我们在Pyhint编辑器的“Pyhint\condition”文件夹下面创建一个test.py文件,然后打开Pyhint编辑器,在代码框中输入以上代码,点击运行后,就会打印出一个文件对象信息,说明open()函数成功打开该文件。如果打开文件失败,就会抛出一个OSError异常。
这里需要注意的是,上面的例子中“test.py”是代表文件的地址,也就是文件存放在哪里。当我们手动打开一个文件时,我们首先要知道文件的存储位置。文件地址可以是绝对路径,也可以是相对路径。绝对路径是最完整的路径,比如“E:\Pyhint\condition\test.py”。相对路径指的是相对于当前文件夹的路径,也就是相对于当前Python解释器的工作目录的路径,“./”表示当前文件夹,“./”可以省略不写,“../”表示上一级文件夹。由于Pyhint编辑器默认的工作目录的路径是“Pyhint\condition”,所以要打开该目录下的test.py文件,可以直接输入相对路径“test.py”或者“./test.py”。如果不知道Python解释器默认的工作目录的路径,可以使用os.getcwd()函数查看。例如:
动手练一练:
import os # 导入 os模块
print(os.getcwd())
2、Python中文件的模式
open(file_name, mode='r')函数中的第二个参数是文件模式。文件模式是指在打开文件时如何访问和操作文件的方式。open()函数如果没有传入第二个参数,则默认模式是“r”,即以只读方式打开文件,文件的指针将会放在文件的开头。文件模式可以是读取模式('r'),写入模式('w'),追加模式('a')或二进制模式('b')等。在Python中,打开文件时可以使用以下模式:
'r':只读模式,用于读取文件内容。文件的指针将位于文件的开头。如果文件不存在,将会抛出FileNotFoundError异常。这是默认模式。
'rb':以二进制只读模式打开文件。类似于‘r’,但以二进制格式读取文件内容,文件的指针将位于文件的开头。
'r+':以读写模式打开文件。文件的指针将位于文件的开头。如果文件不存在,会引发FileNotFoundError。
'rb+':以二进制读写模式打开文件。文件指针将会放在文件的开头。
'w':写入模式,用于写入文件内容。如果文件不存在,将会创建一个新文件;如果文件存在,将会覆盖原有内容。
'wb':以二进制写入模式。如果文件不存在,将会创建一个新文件;如果文件存在,将会覆盖原有内容。
'w+':以读写模式打开文件。如果文件不存在,将会创建一个新文件;如果文件存在,将会覆盖原有内容。
'wb+':以二进制读写模式打开文件。如果文件不存在,将会创建一个新文件;如果文件存在,将会覆盖原有内容。
'a':追加模式,用于在文件末尾添加内容。如果文件不存在,将会创建一个新文件进行写入。
'ab':以二进制追加模式,用于在文件末尾添加内容。如果文件不存在,将会创建一个新文件进行写入。
'a+':以追加读写模式打开文件,写入的内容会追加在文件的末尾。如果文件不存在,将创建新文件用于读写。
'ab+':以二进制追加读写模式打开文件。文件的指针将位于文件的末尾。如果文件不存在,将创建新文件用于读写。
'x':以独占方式创建文件,用于创建新文件并写入内容。如果文件存在,将会抛出FileExistsError异常。
'b':二进制模式,用于读取或写入二进制数据。
't':文本模式,用于读取或写入文本数据。
在上面的模式中,Python在读写文件时会区分二进制和文本两种方式。文本方式(模式中不带有“b”)读写的内容将作为字符串str类型返回,文件内容会根据Python解释器相关的编码或者指定了的“encoding”参数的编码进行解码。二进制方式(模式中带有“b”)以字节序列的形式读取和写入文件中的数据,常用于处理非文本文件,如图像、音频、视频等二进制文件。在读取二进制文件时,Python不会对文件中的数据进行解码,直接返回原始的字节序列;在写入二进制文件时,Python会将字节序列直接写入文件中,不进行编码。
例如,以下代码打开一个名为icon.png的二进制文件,并读取文件中的前10个字节:
动手练一练:
with open('D:\\icon.png', 'rb') as f:
a = f.read(10)
print(a)
执行以上代码,输出结果为:
b'\x89PNG\r\n\x1a\n\x00\x00'
需要注意的是,当以不正确的模式打开文件时,可能会导致数据损坏或程序出错。例如,如果将一个二进制文件以文本模式打开,则文件中的字节序列会被错误地解码为字符串,导致数据损坏。因此,在打开文件时,我们应该根据文件的类型和需求选择正确的模式。
Python中r+与w+文件模式的区别
“r+”和“w+”两种模式在Python中都是用于文件的读写操作,两种模式的主要区别在于处理“文件是否存在”的方式不同。“r+”模式允许对文件进行读写操作,如果文件不存在,则会报错,抛出FileNotFoundError异常,如果文件存在,可以读取和写入数据。“w+”模式同样允许对文件进行读写操作,如果文件不存在,则会创建一个新文件后进行读写操作,如果文件已存在,则会覆盖原有内容,原有内容会被清空,然后可以进行读写操作。
3、Python中的文件编码
计算机一开始发明出来时是为了解决数学问题的,后来人们发现,计算机还可以做更多的事,例如文本处理等。于是,各大厂商想到了使用二进制数来存储阿拉伯数字,a,b,c等字母和其他常用符号等,由于各大厂商没有保持统一,各自搞自己的硬件和软件,想怎么编码就怎么编码。后来,机器间实现相互通信的时候,发现在不同计算机上显示出来的字符不一样。
为了通信的方便,各大厂商需要使用同一套编码才行,否则彼此看不懂,就会造成乱码。
ASCII编码(American Standard Code for Information Interchange)就是美国的标准化组织提出的一套编码,但总共只规定了百来个字母和数字,它使用了7个比特位来表示。但在中国,7个比特位完全不够用,于是中国使用的编码表GB2312使用了16个比特位,也就是两个字节来表示65536个常用汉字。
随着全球化的不断推进,为了全世界可以顺利沟通,Unicode编码表将世界上所有符号全部包含进去,全世界都使用这一套编码标准,所有语言达到互通。基于Unicode又提出UTF-8,可以让每个符号都不必使用相同的字节数来表示,不同符号表示的字节长度也可能不同,减少空间浪费。
默认情况下,现在大部分系统使用的编码都是UTF-8,比如Web应用程序,但Windows操作系统默认使用的编码是GBK,GBK是中国国家标准编码,GBK全称是“汉字内码扩展规范”,英文名称是“Chinese Internal Code Specification”,GBK编码是基于GB2312编码扩展的编码标准。 Python支持中文的编码包括UTF-8、GBK和GB2312。
当我们输入的汉字想让计算机明白,就需要对汉字进行编码encode(),反过来就是解码decode(),例如:
动手练一练:
print("你好".encode('UTF-8'))
print("你好".encode('gbk'))
执行以上代码,输出结果为:
b'\xe4\xbd\xa0\xe5\xa5\xbd'
b'\xc4\xe3\xba\xc3'
上面的例子中,字符串编码后得到的内容前面都有个“b”字母,这代表了它的类型是二进制bytes(字节)类型的数据,“\x”是分隔符,用来分隔相邻的每个字节。编码其本质是将字符串str类型的数据转换成二进制bytes类型的数据。encode()函数的基本用法非常简单,只需要在字符串对象后面加上.encode()即可。
decode()解码操作的方法也比较简单,例如:
动手练一练:
# 假设这是UTF-8编码的字节序列
bytes_data = b'\xe4\xbd\xa0\xe5\xa5\xbd'
# 将字节序列解码成字符串
string_data = bytes_data.decode('utf-8')
# 输出:“你好”
print(string_data)
执行以上代码,输出结果为:
你好