本文主要介绍的是文件的基本操作以及以二进制方式对文件进行操作。
一、文件的基本操作:
在我们对文件进行操作之前,我们首先要打开文件或创建文件(打开的文件不存在时则需要创建文件)。当这个文件对象存在后,我们才可以对这个文件进行操作。所谓的存在不是指文件中要有内容,而是指在计算机系统中有这个文件。
1、创建文件对象
首先我们要知道python中打开文件的语法规则(即如何创建对象):
file=open(filename,mode,encoding)
filename:表示文件名称,通常会写文件所在路径加上文件名称
mode:用于指定文件的打开模式,有'w','r','a','b','+'这五种模式
r | read,表示以只读模式打开文件,即只能对文件进行读取操作(只有文件存在时才可使用该种打开模式) |
w | write,表示以只写模式打开文件,即只能对文件进行写入,并且每次写入时会覆盖文件上次存在的内容(文件不存在则创建文件) |
a | 以追加模式打开文件,每次追加时会追加在文件上次存在的内容的后面(文件不存在时则创建文件) |
b | 以二进制方式打开文件(后面会具体讲解),不能单独使用,需要与其他模式一起使用,如rb |
+ | 以读写方式打开文件,不能单独使用,需要与其他模式一起使用,如r+ |
encoding:用于指定文件的编码格式,如UTF-8、GBK等。通俗的讲,对于一个字符而言,在编码格式a中它表示为数字1000,在编码格式b中它表示为2000,在编码格式b中数字1000代表的是其他字符,所以当我们以编码格式a向文件中写入内容后,计算机内部存储的是数字1000,当读取文件时,要想读取的内容 和 我们当时写入的内容 一致,那么我们也需要以编码格式a来读取文件,否则可能导致读取出来的内容 与 写入的内容不同。后面会详细讲解。
2、文件对象的常用方法
read() | 一次读取文件所有内容,返回值为字符串 |
readlines() | 按行读取文件内容,返回的值是列表,每行的内容为列表中的一个元素 |
write() | 将字符串内容写入文件 |
writelines() | 将字符串列表写入文件(每个元素之间不会添加换行符) |
close() | 关闭文件,释放文件对象相关资源 |
3、文件的读写操作
#首先创建一个文件对象并指定文件对象的打开模式为w
file=open('D:\\Python_learn\\文档.txt','w',encoding='UTF-8')
#w表示以只写模式打开文件,文件不存在则创建文件。文件路径这里使用\\是因为如果单独使用一个\,那么就代表它是转义字符,所以需要在它前面再加一个\,表示它只是一个普通的\
#使用文件对象的write()方法 向文件对象中写入内容
file.write("好好学习,天天向上\n")
#进行完读操作后,文件指针在文件的末尾
file.close() #每次对文件进行操作后,需要关闭文件,释放系统资源。
file=open('D:\\Python_learn\\文档.txt','r',encoding='UTF-8')
#r表示以只读模式打开文件
#使用文件对象的read()方法 读取文件对象中的内容
#如果对文件对象进行写操作后,未关闭文件或者重新移动文件指针的位置,将读取不到任何内容
str=file.read()
print(str) #好好学习,天天向上
file.close()
二、以二进制方式对文件进行操作
首先我们要知道,文件是以二进制数据的形式存储在计算机中的。即,在计算机内部,文件都是以二进制的形式进行存储的。
1、以二进制的方式读取文件(rb)
file=open('D:\\1_Python_learn\\文档.txt','rb') #我们在前面的代码中刚向文档.txt中写入了数据
bin_data=file.read()
file.close()
print(bin_data) #b'\xe5\xa5\xbd\xe5\xa5\xbd\xe5\xad\xa6\xe4\xb9\xa0\xef\xbc\x8c\xe5\xa4\xa9\xe5\xa4\xa9\xe5\x90\x91\xe4\xb8\x8a\r\n'
#读取的结果为字节串,b''表示这是一串字节串,\x表示是十六进制的数据,将十六进制e5转换为二进制,就可以转换为一个字节的二进制数据。一个字节的二进制数据转换为十进制,范围是0-255。
#遍历字节串
for i in bin_data:
print(i,end=' ')
#229 165 189 229 165 189 229 173 166 228 185 160 239 188 140 229 164 169 229 164 169 229 144 145 228 184 138 13 10
#字节串是序列类型的数据结构,既然字节串是一个序列,那我们就可以对它进行遍历。一个字节的二进制数据就表示 字节串中的一个元素,而一个字节的二进制数据转换为十进制,范围是0-255。所以我们遍历前面的字节串,就可以得到上面的这一串整数。即字节串是由0-255范围内的整数构成的序列,但是它并不是整数列表。
当我们以二进制的方式读取文件时,可以发现,我们指定编码格式时,代码会报错。首先我们要知道为什么读取文件和写入文件时要指定编码格式。
在不同的编码格式中,每个字符对应的数值可能不同,同一个英文字符在不同的编码格式中对应的数值一般相同,因为UTF-8、GBK这些编码格式都是沿用的ASCII码中每个字符对应的数值,但是ASCII码中又只有英文字母、数字、运算符、英文标点符对应的数值。比如在ASCII码中,英文字母a对应的编码为整数97,在UTF-8、GBK这些编码格式中英文字母a对应的数值都为97。我们可以注意到,ASCII码中没有中文字符,所以在不同的编码格式中,中文字符对应的数值很可能是不同的。比如下面的案例,福字在UTF-8和GBK编码格式中所对应的编码就不同。
str='福'
print(str.encode('utf-8')) #b'\xe7\xa6\x8f'
print(str.encode('gbk')) #b'\xb8\xa3'
print()
#使用encode()方法可以得到一个字符串按照指定的编码格式 编码成字节串
#通过上面的结果,我们可以看出在不同的编码格式中,中文字符'福'所对应的字节串是不相同的,也就意味着它在不同的编码格式中所对应的整数数值不同
当我们以只读模式('r')打开文件时,我们最终读取到的结果是文件中的内容。其实读取时最初从计算机系统中获取到的还是二进制数据,但是程序就会将读取的二进制数据 按照指定的编码格式来解码(每种编码格式都有它对应的编码表,计算机通过查找编码表,将二进制数据解码为对应的字符),并将解码后的数据返回给我们,所以我们看见的都是按照指定编码格式 解码后的数据(即各种字符,中文字符、英文字符、特殊符号等),所以普通的读操作的时候必须要指定编码格式,否则计算机不知道按照何种编码格式来解码字节串了。
但是以二进制的形式读取文件时,我们本身就想读取到的 就是二进制数据。那么就无需指定编码格式,即使可以指定,指定了也没有任何意义,因为我们并不需要解码。
2、以二进制的方式写文件(wb)
str='三天打鱼,两天晒网'
file=open('D:\\1_Python_learn\\文档.txt','wb')
bin_data=bytes(str,encoding='UTF-8') #使用bytes()函数将字符串按照指定的编码格式 编码为字节串
file.write(bin_data)
#以二进制的方式写文件时,如果使用的write方法,需要先把字符串转换为对应的字节串,才能使用write()方法进行写入。
file.close()
file=open('D:\\1_Python_learn\\文档.txt','r',encoding='UTF-8')
str2=file.read()
file.close()
print(str2) #三天打鱼,两天晒网
上面的示例中,我们是以UTF-8编码格式 将字符串进行编码后再写入文件中的,且我们读取文件的时候,指定的也是UTF-8编码格式,所以最终得到的str2才和str的值相等。假如我们写入和读取的编码格式不一致,那么在有中文字符的情况下,很有可能读出来的内容为乱码,原因也在前面做过简单的解释了,因为中文字符在不同的编码格式中对应的编码可能不一致。
str='三天打鱼,两天晒网'
file=open('D:\\1_Python_learn\\文档.txt','wb')
bin_data=bytes(str,encoding='UTF-8')
file.write(bin_data)
file.close()
file=open('D:\\1_Python_learn\\文档.txt','r',encoding='GBK')
str2=file.read()
print(str2)
运行上面的示例,代码会有报错,因为按照GBK的编码格式无法正常解码 我们将字符串按照UTF-8格式转换出来的字节串(就是二进制数据)。所以为了保证可以正常读到写入的数据,请记得把写入和读取的编码格式设置为一致。
我们在向文件中写入内容时,设置编码格式是为了将字符串 按照指定的编码格式进行编码,也就是将字符串中的字符 按照指定编码格式的编码表 转换为对应的二进制数据,再存储进我们的计算机中。所以向文件中写入内容时,一定要指定编码格式,否则计算机就不知道按照何种编码格式 编码文件内容了。
3、以二进制的方式操作文件的应用
以二进制的方式操作文件,可以应用于图像处理、音频和视频剪辑、数据加密等方面。关于实现文件内容的加解密这方面,详细内容可参考下面这篇文章: