共计 12615 个字符,预计需要花费 32 分钟才能阅读完成。
文件操作
咱们能够应用 python 来操作文件,比方读取文件内容、写入新的内容等,因为任何计算机文件的实质都是一些有不同后缀的字符组成的。
python 文件操作的两种模式
关上模式
- while,写入模式,简写为 w,指定的文件不存在则创立文件,存在则关上并清空内容,并且将文件指针(光标)放在文件的结尾。
- read,读取模式,简写为 r,文件不存在则报错,存在则关上文件,并且将文件指针放在文件的结尾。
- append,追加模式,简写为 a,文件不存在则创立文件,存在则关上文件,并且将指针放在文件开端。
- xor,异或模式,简写为 x,文件存在则报错,不存在则创立文件,将文件指针放在文件的结尾。
扩大模式
扩大模式是用来配合关上模式的辅助模式,扩大模式独自不能应用。
- plus,加强模式,简写为 +,能够让关上模同时具备读写性能。
- bytes,bytes 模式,简写为 b,将文件依照二进制字节流编码进行读写。
因而咱们依据这两种大的模式能够组合成为 16 种操作文件的办法。
模式 | 作用 | 模式 | 作用 |
---|---|---|---|
w | 写入模式,只可写,不可读。 | a | 追加模式,只可写,不可读。 |
w+ | 写入模式,可写可读。 | a+ | 追加模式,可写可读。 |
wb | 写入模式,依照二进制字节流编码可写不可读 | ab | 追加模式,依照二进制字节流可写不可读 |
wb+ | 写入模式,依照二进制字节流编码可写可读 | ab+ | 追加模式,依照二进制字节流可写可读。 |
r | 读取模式,只可读,不可写。(默认模式) | x | 异或模式,只可写,不可读。 |
r+ | 读取模式,可写可读。 | x+ | 异或模式,可写可读。 |
rb | 读取模式,依照二进制字节流编码可读不可写。 | xb | 异或模式,二进制字节流可写不可读。 |
rb+ | 读取模式,依照二进制字节流编码可读可写。 | xb+ | 异或模式,二进制字节流可写可读。 |
异或模式和写入模式的区别在于,异或模式如果关上的文件在指定的门路中如果存在,就会报错;而写入模式是间接关上不会报错,然而会将源文件中的所有内容清空。因为写入模式和读取模式之间的互相配合,异或模式的应用频率越来越少,正在逐渐淘汰当中。
编码格局的理解
编码是信息从一种模式或格局转换为另一种模式的过程,就是用预先规定的办法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。这样做的目标是为了简化信息之间的传递。然而为保障编码的正确性,编码要规范化、标准化,即需有规范的编码格局。常见的编码格局有 ASCII、ANSI、GBK、GB2312、Unicode、UTF- 8 等。
所有的编码格局,都是将字符转换成对应的二进制格局。将东方的字母文字和数字依照一个字节的形式存储,而将亚洲中中、日、朝等文字依照多字节存储。这是因为东方的字母语言,字母的数量远少于西方的文字数量,因而编程工作中个别更加的偏向与尽量多的应用英文的起因,因为绝对的来说应用汉字等字符较少的程序能够占据更少的系统资源。
罕用的编码格局
英文原始编码:ASCII 码
ACSII 编码只有 128 个字符,26 个英文字母的大小写之外,还有一些罕用的符号,还有一些不可或缺的零碎控制字符等。ACSII 编码中没有除了英文字母之外的其它语言字符。
中文国家标准编码:GB 系列编码
但凡由 GB 结尾的编码集都是属于中国国家的规范编码字符集,只是不同的版本而已,应用这个编码的汉字占用的系统资源起码,中文应用 2 个字节的存储空间。比方 GB2312。
万国码:Unicode 编码
Unicode 编码蕴含世界上所有的文字,无论什么字符都以 4 个字节进行存储。这是 Unicode 编码的毛病,尽管领有世界上最齐全的字符,然而占用的系统资源很大,所以很少应用。
因而在这个根底之上改良,创立了可变长的 Unicode 编码集,UTF 系列。这是目前世界上最支流的编码字符集,在这个编码集当中,不必放心任何字符会乱码,字母文字和数字应用一个字节的存储空间,中文等字符应用三个字节的存储空间,大大节俭了空间的占用。比方 UTF-8。
open 函数的应用
python 中操作文件要应用到 open 函数,open 函数的作用是用于关上一个文件,创立一个 file 对象,应用相干的办法调用它对文件进行读写操作。
语法:open(file, mode=None, encoding=None)
参数阐明:
- file:文件的地位和名称
- mode:操作的模式,应用简写,就是咱们上述的 16 中操作形式
- encoding:指定编码类型,比方 UTF-8、GB2312、ACSII 等
open 函数指定这些信息之后,返回一个 TextIOWrapper 对象,应用这个对象,咱们能够依照指定的操作模式和编码格局来操作咱们指定的文件。
文件的写入(写入模式)
当初咱们在应用 open 函数创立一个文件,并写入内容。
能够看到咱们以后的目录当中只有一个 main.py 文件,咱们当初写入代码。
# 指定文件的地位,要应用字符串,能够应用绝对路径和相对路径
# 操作模式的抉择,咱们要创立一个新的文件并写入内容,应用 w
# 指定编码格局为 UTF-8,这是最常应用的编码格局
# fp 就是文件的 IO 对象,问价句柄,用来操作文件
# i --- > input 输出
# o --- > output 输入
fp = open('test.txt', 'w', encoding='UTF-8')
# 应用 write 函数写入内容
fp.write('Hello motherland')
# 应用 close 函数敞开文件
fp.close()
执行 python 代码之后,咱们发现在原来的目录上面多出了一个名为 test.txt 的文件。
关上这个文件咱们就会发现,文件中的内容就是咱们写下的内容。
当初咱们从新应用 w 模式关上这个文件,然而不操作任何货色,让咱们看看后果如何。
fp = open('test.txt', 'w', encoding='UTF-8')
fp.close()
没错,这个文件中的内容被清空了,这就是 w 模式的如果文件存在,就关上文件并清空。
文件的读取(读取模式)
咱们当初执行上面的代码,应用 r 模式读取文件中的内容。
# 应用 r 模式关上 msr.txt 文件
fp = open('msr.txt', 'r', encoding='UTF-8')
# 读取文件中的内容
res = fp.read()
print(res)
# 敞开文件
fp.close()
发现程序报错了,这是为什么?因为应用 r 模式如果指定的文件不存在就会报错。
那咱们先创立一个 msr.txt 文件在从新读取一下。
# 先创立一个 msr.txt 文件
fp = open('msr.txt', 'w', encoding='UTF-8')
# 写入内容
fp.write('刘德华太帅了。')
# 敞开文件
fp.close()
# 而后从新读取这个文件
fp = open('msr.txt', 'r', encoding='UTF-8')
# 读取文件中的内容
res = fp.read()
# 打印读取的内容
print(res) # 刘德华太帅了。# 敞开文件
fp.close()
不再报错了,而且也胜利的打印进去文件中的内容。
文件内容追加(追加模式)
追加模式如果文件不存在就创立文件,反之就关上文件,然而可写入模式的不同之处就在于,追加模式关上文件不会清空文件中的原有的数据内容。
关上 msr.txt 文件,咱们看到只有一行文字。
当初咱们执行上面的代码
# 应用追加模式关上文件
fp = open('msr.txt', 'a', encoding='UTF-8')
# 在文件中写入内容
fp.write('然而刘德华没有博主帅。')
# 敞开文件
fp.close()
关上文件咱们看到,原有的数据并没有被清空掉,并且写入了新的内容。
[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-monzJF4R-1647692650673)(
)]
字节流的转换
bytes 是用来传输或者是存储的数据格式,如果是在文件的操作过程中依照 bytes 的模式操作的话,就须要将数据格式转换成为 bytes 流才能够。
二进制的字节流就是底层的代码。
应用 b 前缀
在字符串之前加上字符 b 代表是二进制的字节流,然而范畴只是 ASCII 编码,也就是说这样并不反对中文。
# 在字符串之前加上 b 前缀
bytechar = b'hello motherland'
print(bytechar) # b'hello motherland'
# 该字符串的数据类型就变成了 bytes 流
print(type(bytechar)) # <class 'bytes'>
bytechar = b'你好祖国' # error,只能将 ACSII 编码中的字符变成 bytes 流
应用函数
应用 encode 函数和 decode 函数能够将字符串在一般字符串和字节流的模式中来回的转换,而且能够将所有的字符变成 bytes 字节流,因为默认应用 UTF- 8 编码,当然你也能够指定转换的编码格局。
函数 | 作用 |
---|---|
encode | 将字符串转换为二进制的字节流 |
decode | 将二进制的字节流转换为字符串 |
语法:
string.encode(encoding=’UTF-8′)
bytes.decode(encoing=’UTF-8′)
var = '我的祖国'
# 将字符串变成字节流,默认应用 UTF- 8 编码
res = var.encode()
print(res) # b'\xe6\x88\x91\xe7\x9a\x84\xe7\xa5\x96\xe5\x9b\xbd'
print(type(res)) # <class 'bytes'>
# 指定编码格局 UTF-8
res = var.encode(encoding='UTF-8')
print(res) # b'\xe6\x88\x91\xe7\x9a\x84\xe7\xa5\x96\xe5\x9b\xbd'
# 能够看到指定为 UTF- 8 编码的和默认的后果是一样的
# 指定编码格局为 ASCII
res = var.encode('ASCII') # error
# 因为原字符串是中文,所以不能应用 ASCII 编码
# 指定为 GBK 编码
res = var.encode('GBK')
print(res) # b'\xce\xd2\xb5\xc4\xd7\xe6\xb9\xfa'
# 能够看到 GBK 的编码中文能够节俭更多的空间
# 能够应用 len 函数检测字节流的长度
print(len(res)) # 8
# 解码
var = res.decode() # error
# 应为默认应用的 UTF- 8 解码,然而 res 的编码格局是 GBK,所以失败
# 只能应用对应的编码格局解码
var = res.decode('GBK')
print(var) # 我的祖国
存储二进制的字节流
如果在操作文件的时候要应用字节流的形式,在应用 open 函数抉择模式的时候要加上 b,示意进行字节流的操作,而后 open 函数就不能在指定编码格局了,因为当初的操作的都是字节流,然而字节流自身就曾经是指定的编码格局编码过了。
# 如果指定了字节流模式还要指定 encoding 参数就会报错
fp = open('test.txt', 'wb', encoding='UTF-8') # error
# 应用字节流模式只能进行字节流的写入
fp = open('test.txt', 'wb')
# fp.write('hello motherland') # error,不能间接应用字符串
fp.write(b'hello motherland')
fp.write('我的祖国'.encode())
fp.close()
写在文件中的内容还是原来的样子,不是字节流的模式
注意事项:
- 应用字节流模式编辑过的文件只能应用字节流模式去操作
- 应用什么格局的字节流写入文件的内容,读取的时候只能应用对应的编码格局去解码
- 任何文件都能够应用字节流模式去读取内容,读取的内容是字节流,如果这个文件是依照某个编码格局写入的,解码须要应用对应的编码格局;如果这个文件的内容不是应用字节流模式写入,读取的字节流默认是 UTF- 8 格局的。
上下文管理器
在 python 中,有一些工作是当你开启之后,完结的时候须要专门的敞开工作,比方文件操作,在完结操作的应用须要应用 close()函数专门的敞开文件、结束任务,这样就很繁琐,所以 python 中推出了 with …… as ……
的语法,在 with 代码块中如果完结操作,不须要在专门的结束任务。
上下文管理器,任何须要进行上下文操作的对象,都能够应用此语法。
语法:with 工作 as 操作句柄:
# 不须要在应用 close()函数专门的敞开文件,结束任务了
with open('test.txt', 'wb') as fp:
fp.write(b'hello motherland')
刷新缓冲区
咱们学习了这么久,每次都肯定要敞开文件、结束任务,这样做的意义是什么?
比拟直观的目标就是为了保留文件 ,然而好奇的咱们早就测试了不应用 close() 敞开文件,写入的内容一样是保留了文件中的,这是怎么回事?
看上面的代码,发现咱们文件中仍然是保留了咱们写入的内容。
fp = open('test.txt', 'w', encoding='UTF-8')
fp.write('我和我的祖国,就像是海和浪花一朵。')
这是因为,敞开文件的基本目标是为了刷新缓冲区,然而刷新缓冲区的办法不止一种。
- 当文件敞开的时候主动刷新缓冲区
- 当整个程序运行完结的时候主动刷新缓冲区
- 当缓冲区写满还主动刷新缓冲区
- 手动刷新缓冲区
刷新缓冲区的意义在于最初的保留文件,就如同在应用文档编辑器的时候,尽管写满内容,但最初不点击保留按钮内容也不会保留下来。
而咱们下面的例子就是因为程序运行完结的时候主动刷新了缓冲区,所以才保留了写入文件的内容,而 close 的作用就是敞开文件,敞开文件也能够刷新缓冲区,所以这就是每次要敞开文件的起因所在,为了避免主动刷新的失败。
那么什么状况之下程序就没有方法执行完呢?
比如说程序的意外中断、或者是死循环,上面的代码中就是因为死循环的起因导致程序没有方法执行实现,而没有保留新写入的内容。
上面的代码,先是写入了内容,而后就是一个死循环,这样程序永远都不会执行实现,就不能主动的刷新缓冲区,如果程序意外中断,内容也不会写入文件当中,你能够将程序运行起来之后,强制中断测试一下,会发现是一个空文件。
with open('test.txt', 'w', encoding='UTF-8') as fp:
fp.write('我和我的祖国,一刻也不能宰割。')
while True:
pass
手动刷新
下面的例子中,文件没有方法敞开,程序没有方法执行实现,貌似缓冲区也很难写满,难道咱们的内容就没有方法保留了吗?
你机智的写上了一行代码,是 close()函数,这样就敞开了文件,就能够将死循环之前的内容保留了嘛。
with open('test.txt', 'w', encoding='UTF-8') as fp:
fp.write('我和我的祖国,一刻也不能宰割。')
fp.close() # 敞开文件
while True:
pass
你通过测试,下面的代码确实的保留了写入的内容,然而咱们敞开了文件,再次操作文件的时候就必须从新开启文件,不然没有方法持续操作。
with open('test.txt', 'w', encoding='UTF-8') as fp:
fp.write('我和我的祖国,一刻也不能宰割。')
fp.close()
fp.write('我和我的祖国,就像是海和浪花一朵。') # error,文件曾经敞开
while True:
pass
发现写入的第二条内容基本就没法执行了,怎么办?应用 fiush()函数手动刷新缓冲区。
with open('test.txt', 'w', encoding='UTF-8') as fp:
fp.write('我和我的祖国,一刻也不能宰割。')
fp.flush()
fp.write('我和我的祖国,就像是海和浪花一朵。')
fp.flush()
while True:
pass
发现手动刷新将内容保留了下来,而且没有影响程序的执行。当前如果程序工作过大,没有执行实现就意外中断,这样就有一点数据保留不下来的危险,咱们就能够隔着一段工作手动刷新一下,就不至于将所有的数据全副失落。
文件的扩大模式
咱们通过下面的学习,用到了写、读、手动刷新、敞开文件等几种操作文件的函数,然而除此之外,还有一些罕用的相干函数。
函数 | 作用 |
---|---|
write | 写入数据 |
read | 读取数据 |
fiush | 手动刷新缓冲区 |
close | 敞开文件 |
seek | 调整指针(光标)的地位 |
tell | 返回以后指针左侧所有的字节数 |
readable | 判断文件对象是否可读 |
writeable | 判断文件对象是否可写 |
readline | 读取文件的一行内容 |
readlines | 将文件中的内容依照换行读取到列表当中 |
writelines | 将内容是字符串的可迭代数据写入文件当中 |
truncate | 把要截取的字符串提取进去,而后清空内容并将截取的内容从新写入 |
read 的应用
plus 加强模式的应用
在 open 函数中,应用 + 号,进入加强模式,可读可写。
咱们当初应用 r+ 模式关上之前的文件,读取其中的内容。
with open('test.txt', 'r+', encoding='UTF_8') as fp:
# 读取内容
res = fp.read()
print(res) # 我和我的祖国,一刻也不能宰割。我和我的祖国,就像是海和浪花一朵。# 能够指定字符的个数,读取指定个数的字符
res = fp.read(5)
print(res) #
发现什么第二遍没有读取出任何的内容,咱们从新关上一遍文件,从新读取。
with open('test.txt', 'r+', encoding='UTF_8') as fp:
# 读取五个字符
res = fp.read(5)
print(res) # 我和我的祖
# 再读取五个字符
res = fp.read(5)
print(res) # 国,一刻也
发现第二遍读取的内容是接着第一遍读取的内容之后的,咱们从新关上一遍文件,写一些内容。
with open('test.txt', 'r+', encoding='UTF_8') as fp:
# 写入内容
fp.write('我永远和我的祖国在一起')
# 读取其中的内容
res = fp.read()
print(res) # 能宰割。我和我的祖国,就像是海和浪花一朵。
读取内容的时候,发现没有咱们写入的内容,而且读取的文件内容怎么看起来好怪异的感觉啊,怎么少了些内容?
咱们从新关上文件读取一遍
with open('test.txt', 'r+', encoding='UTF_8') as fp:
res = fp.read()
print(res) # 我永远和我的祖国在一起能宰割。我和我的祖国,就像是海和浪花一朵。
为什么咱们的写入的内容在文件的结尾,而且还替换掉了原有的一部分数据?咱们下面的一系列操作为什么那么的奇怪?
这都是因为光标的作用在做怪。
光标的作用
还记得咱们之前介绍四种关上模式的时候吗?写入模式光标在文档最初,读取模式光标在文档最前,追加模式光标在文档最前,异或模式光标在文档最前。
写入的内容和读取的内容都是从光标的地位开始的。
read()函数默认读取光标一右侧所有的内容。而不是文档中的所有内容,之前的测试之所以能够一次性的读取出所有的内容是因为咱们打开文档应用的是读取模式,光标的地位在文档的结尾。光标会随着读取的内容而挪动,读取到哪个字符光标就挪动到哪个字符的前面。
write()写入内容的时候是笼罩模式。咱们都晓得咱们的计算机系统中的文本输出形式是有两种的,应用 insert 键就能够切换着两种模式。一种是插入模式,一种是笼罩模式。
插入模式是咱们平时最常常应用的,比如说咱们关上一个文本编辑软件,轻易的写入一段内容,而后把光标挪动到文档的结尾,写入内容,发现新的内容是插入到了旧的内容之前的,旧的内容不会隐没,而是后移,这就是插入模式;而后从新将光标挪动到文档的结尾,而后按下 insert 键,这个时候你的输出形式就变成了笼罩模式,当初的你每当输出一个新的字符就会笼罩掉前面的一个旧字符,这就是笼罩模式,python 的文本编辑就是这种笼罩模式。光标随着写入的内容向后挪动。
光标地位的挪动
咱们方才的时候就理解到了有一个能够调整光标地位的函数,叫做seek,应用这个函数咱们能够随便的调节光标的地位,从而编辑文件的时候能够更加的得心应手。
seek(offset: int, [whence: int = 0])
seek(偏移量, [基准地位])seek 函数的两个参数都是整型。
第一个参数示意的是偏移量,独自应用时示意将光标挪动到从文档的结尾算起的第 N 个字节的地位后;
第二个参数示意的光标的地位,应用的时候只有 0、1、2 三个选型,且偏移量必须为 0;0 代表的是文档的最开始 1 代表的是光标的以后地位 2 代表的是文档的最初端
# 先应用 w+ 模式关上一个文件,这个时候的文件为空,光标在文档的结尾地位
with open('test.txt', 'w+', encoding='UTF-8') as fp:
# 咱们写入内容,这个时候光标的地位随着写入的内容到了文档的最初
fp.write('hello motherland.')
# 所以当初的光标的右侧没有任何一个字节符,所以读不出任何的内容
res = fp.read()
print(repr(res)) # ''
# 所以光标还是在最初的地位,应用 seek 切换光标的地位为结尾,读取方才写入的内容
fp.seek(0)
res = fp.read()
print(repr(res)) # 'hello motherland.'
# 读取完内容之后,光标又到了文档的最初的地位,调整到结尾的第五个字节符的地位
fp.seek(5)
# 再次读取文件的内容,这一次只读取 5 个字符,发现前五个字符没有了
res = fp.read(5)
print(repr(res)) # 'moth'
# 当初光标在文档的第十个字符地位,咱们将光标切换到文档的最初,而后读取文档发现什么内容也没有
fp.seek(0, 2)
res = fp.read()
print(repr(res)) # ''
留神到了吗?我说的 seek 挪动的是 字节的数量,什么是字节的数量?
咱们之前说的不同的编码格局对于不同的字符都是不一样的,然而所有的编码格局对于英文字母为主的一些的字符都是一个字节的大小,然而汉字不一样,汉字在 GB 中是两个字节、UTF 中是三个字节、Unicode 中是四个字节。
seek 的偏移单位是字节,不是字符,所以在应用 seek 在操作 bytes 字节流时,要留神挪动的距离,因为挪动的是字节位数,而在 GB 编码中一个汉字两个字节,在 Unicode(UTF-8)中,一个汉字三个字节,如果 seek 将指针挪动至汉字之间,就会导致读取时汉字的编码不残缺而导致谬误。
# 从新写入一个文件,留神咱们的编码格局
with open('test.txt', 'w+', encoding='UTF-8') as fp:
fp.write('我和我的祖国,一刻也不能宰割。我和我的祖国,就像是海和浪花一朵。')
# 咱们当初读取除了第一句话之后的内容,后面的内容一共是 15 个字符,咱们应用 seek 跳过去
fp.seek(15)
res = fp.read()
print(repr(res)) # '国,一刻也不能宰割。我和我的祖国,就像是海和浪花一朵。'
# 咦?怎么只跳过了五个汉字?因为咱们应用的 UTF- 8 的编码,一个汉字由 3 个字节,真好是 15 个单位
# 你是侥幸的,如果咱们在右移一个字节的单位,就是一个汉字都没有齐全迁徙完会怎么样?fp.seek(1)
# res = fp.read()
# print(res) # error,报错了,因为剩下的字符不是残缺的,所以没有方法读出,就报错了
# 就像是你好的 UTF- 8 编码是六个字节组成的,print('你好'.encode()) # b'\xe4\xbd\xa0\xe5\xa5\xbd'
# 如果去掉了一个字节,就是不残缺的了,还能解码进去吗?print(b'\xbd\xa0\xe5\xa5\xbd'.decode()) # error,解码失败
所以在应用 seek 函数的时候肯定要慎用。
tell 的应用
# tell 以后光标左侧所有的字节数(返回字节数)# 应用浏览模式关上文件
with open('test.txt', 'r+', encoding='UTF-8') as fp:
# 应用 tell 函数查看贯标左侧的字节数
res = fp.tell()
print(res) # 0
# 因为浏览模式的光标在文件的结尾,所以返回 0 个字节数
# 应用 seek 将光标挪动到文档的开端
fp.seek(0, 2)
# 应用 tell 查看整个文档的字节数,这就是文档的大小
res = fp.tell()
print(res) # 96
# 快去看看你的文件信息中的文件大小是不是 96 字节的?
其它的相干函数
判断文件对象可读可写
# 应用 r+ 模式关上文件
with open('test.txt', 'r+', encoding='UTF-8') as fp:
# 应用 readable 和 readable 查看这个文档是否可读可写
if fp.readable():
print('本文档可读')
if fp.writable():
print('本文档可写')
'''
后果:本文档可读
本文档可写
'''
readline
读取一行内容
# 关上文件,从新写入多行内容
with open('test.txt', 'w+', encoding='UTF-8') as fp:
# 能够应用多行字符串
fp.write('''11111
22222
33333
''')
# 也能够应用转义字符进行换行
fp.write('44444\n55555\n66666')
with open('test.txt', 'r+', encoding='UTF-8') as fp:
# 应用 read 读取的整个文档的内容
res = fp.read()
print(res)
'''
后果:11111
22222
33333
44444
55555
66666
'''
# 应用 readline 读取一一行的内容
fp.seek(0)
res = fp.readline()
print(res) # 11111
# 再读取一行
res = fp.readline()
print(res) # 22222
# 能够指定读取的字符个数
res = fp.readline(3)
print(res) # 333
# 如果指定的个数大于本行的字符个数,就读取本行所有的内容
res = fp.readline(1000)
print(res) # 33
# 为什么是 33 不是 44444?因为 readline 也要受到光标的影响
readlines
将文件中的内容依照换行读取到列表中
with open('test.txt', 'r+', encoding='UTF-8') as fp:
res = fp.readlines()
print(res) # ['11111\n', '22222\n', '33333\n', '44444\n', '55555\n', '66666'
留神:readlines 不会影响光标的挪动,然而读取的是光标的右侧数据;而且 readlines 的读取将换行符也读取上了,因为换行符自身也是一行的内容。
按行读取内容我个别应用到 readlines
函数,然而也能够应用其它的办法,比方间接遍历 open
实例化对象,open
实例化对象自身就是一个可迭代对象,它将文件中的内容依照换行符离开。
with open('text.txt', 'r', encoding='UTF-8') as fp:
for line in fp:
print(line)
writelines
将内容是字符串的可迭代性数据写入文件中,writelines 不会依据元素换行。
lst = ['china', 'america', 'russia']
with open('test.txt', 'w+', encoding='UTF-8') as fp:
# 应用 writelines 写入内容
fp.writelines(lst)
fp.seek(0)
# 读取数据
res = fp.readlines()
print(res) # ['chinaamericarussia']
truncate
文件中的内容只保留截取的内容。
从文件结尾开始,截取指定 字节长度 的内容,而后将文件清空,而后将截取的内容从新填入文件中。
# 关上一个文件
with open('test.txt', 'w+', encoding='UTF-8') as fp:
# 写入一段内容
fp.write('1234567890')
# 保留截取的内容,只保留前 5 个字节的内容
fp.truncate(5)
# 查看文件的内容
fp.seek(0)
res = fp.read()
print(res) # 12345
对于生成文件 MD5 心得
我在工作时须要给调用翻译狗的一个 API,用于上传文献并翻译返回,然而对方须要文件 MD5 进行验证,咱们须要在接入接口的时候,须要将文件 md5 传入,这个时候就呈现了一些问题,我在传入文件和文件 MD5 的时候,被对方回应 文件 MD5
不匹配,我很好奇,为什么会呈现这样的状况?
我在应用这个接口当中,有好几处中央比方 token 的生成和文件 md5 的中央都会须要 md5 加密,所以为此咱们专门将生成 md5 的代码封装成为一个函数(将字符串输出,返回 md5,代码如下:
import hashlib
def enMD5(target):
"""MD5 加密"""
res = hashlib.md5(target.encode()).hexdigest()
return res
python 中生成 md5 须要输出字节流格局的数据,而我一开始只有字符串的数据须要应用 md5 加密,所以我在函数中将字符串变成字节流。token 就是传入字符串失去的。
然而文件 md5 的话能够间接读出字节流的格局,然而因为再应用这个函数不不便,所以我应用失常读取文档的形式读取文件中的内容,而后放入函数中,后果就是下面说的,和对方得出的文件 md5 并不匹配。我自认为我的代码是没有问题的,于是咱们顺次查找问题的所在,起初我发现网上很多博主的办法都是间接从文件读取二进制字节流的形式获取的,我切实是没有方法了,就想会不会就是读取形式的问题呢?果然,我就发现不同格局读取的进去的后果是不同的,测试的案例如下:
with open(file_path, 'w', encoding='UTF-8') as fp:
fp.write('msr\nhello\r\nmotherland.')
with open(file_path, 'rb') as fp:
print(fp.read())
with open(file_path, 'r', encoding='UTF-8') as fp:
print(r'f', repr(fp.read()), sep='')
上述的后果为:
b'msr\r\nhello\r\r\nmotherland.'
f'msr\nhello\n\nmotherland.'
没错,我发现间接应用 b
模式和一般模式读取内容而后转化成为 bytes
的后果是不同的,那么也必将导致最初文件 md5 是不正确的。大家也看到了,不论是哪一种读取的办法其实和我写入的内容都是不同的,在本次的测试案例当中对于换行有着不同的认知,读取的起因我没有深刻理解,然而我留神到了官网文档中说 b
模式就是专门读取文件字节流格局的,所以当前大家 生成文件 md5 的时候,肯定要间接应用 b
模式读取文件内容。
上述的测试环境是:
python: python3.6.8_win_x64(Cpython)system: windows_10_x64