一、b模式
b即二进制binary,读写单位均为bytes!
- 读写都是以bytes,即字节为单位
- 可以是任意类型文件,因为计算机任何类型数据都是以bytes模式存在,因此适用范围较t广泛!
- 不能指定字符集!
with open(r'haha', 'rb') as go:
rw = go.read()
print(rw)
# 执行pycharm得到结果
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
b'\xe4\xb8\x89\xe6\xba\xaa666'
# utf-8的中文字符占位三个字节,英文字符和数字仅占一个字节
上述结果,b即bytes格式,而内容大家会发现一堆十六进制后面跟了个666,而实际上我在haha里面写的内容是“三溪666“,为什么会这样呢?因为bytes模式将二进制数据直接写入内存,不做任何转换,但是Python为了阅读方便,自动将01010101的二进制数据转换成了十六进制(虽然我还是觉得无法阅读)!因为英文字母和数字是天生兼容的,所以可以正常显示,但是其它语言的字符就无法直接展示了,只能通过解码方式来正常显示!如下所示:
with open(r'haha', 'rb') as go:
rw = go.read().decode('utf-8')
print(rw)
# 执行pycharm得到结果
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
三溪666
二、read、write新用法
2.1、readline()
因为read是直接从头读到尾,当文件内容过多时,会占用大量内存空间,因此有了readline()只读一行!
先来看看文件总行
sanxi@sanxi-PC:~/Desktop$ cat laiba.txt
come on
hahha
667788
接着在pycharm执行
with open('/home/sanxi/Desktop/laiba.txt', mode='rb') as comnent:
var = comnent.readline()
print(var)
# 在pycharm执行得到结果
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
b'come on\n'
2.2、 readlines()
读所有行,每一行当做一个元素放在一个列表中!
with open('/home/sanxi/Desktop/laiba.txt', mode='rb') as comnent:
var = comnent.readlines()
print(var)
# 在pycharm执行得到结果
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
[b'come on\n', b'hahha\n', b'667788']
2.3、writeines()
相当于for循环,从容器类型取出值连续写入,不过仅适用字符串类型数据!
with open('/home/sanxi/Desktop/laiba.txt', mode='rb') as comnent:
var = comnent.readlines()
with open(r'laiba', mode='wb') as com:
com.writelines(var)
print(var)
# pycharm执行得到结果
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
[b'come on\n', b'hahha\n', b'667788']
再来看laiba文件,内容已经被连续写入
2.4、readable()
是否可读
2.5、writeable
是否可写
2.6、closed
是否关闭
三、flush与拷贝案例修改
3.1、flush()
主要用于写操作,即立刻将数据从内存写入磁盘!
3.2、拷贝案例修改
把之前的拷贝小程序改一改,用b模式!但因为read是直接从头读到尾,可能会占用大量内存空间,因此这次不用read,用for循环和while+readline!
3.2.1、for循环
src = input('请输入需要复制的文件路径:')
dest = input('请输入目标路径:')
with open(src, 'rb') as src_path, open(dest, 'wb') as dest_path:
for line in src_path:
dest_path.write(line)
dest_path.close()
# 执行pycharm得到结果,因为之前说过w模式下不关闭文件,则相当于追加
请输入需要复制的文件路径:/home/sanxi/Desktop/gaga.txt
请输入目标路径:/home/sanxi/PycharmProjects/untitled1/gaga
Process finished with exit code 0
# 去看看gaga的内容
come on
hahha
667788
3.2.2、while循环
src = input('请输入需要复制的文件路径:')
dest = input('请输入目标路径:')
with open(src, 'rb') as src_path, open(dest, 'wb') as dest_path:
while True:
read = src_path.readline()
dest_path.write(read)
if len(read) == 0:
break
dest_path.close()
四、文件指针移动操作
Python中文件指针移动的单位都是以bytes为单位,只有一种特殊情况,也就是t模式下的read(n),n代表的是字符个数,其余都是以字节为单位!既然如此,祭出seek来完成控制文件指针移动!
4.1、seek()
语法:seek(n,mode),n指的是指针的移动都是bytes个数
4.1.1、3种mode:
只有0模式可以在t下移动,1、2必须在b模式下用
4.1.1.1、0模式
0模式代表参照物是文件开头位置,N即表示向后移动N个字节!
# 文件内容:come朋友
with open('gaga', mode='rb') as src:
src.seek(4, 0)
rea = src.readline()
print(rea.decode('utf-8'))
# 执行pycharm得到结果,注意如果是中文的utf-8占位3个字节,如移动到三个字节中的一个而不完整,会报错
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
朋友
4.1.1.2、1模式
即当前指针所在位置
4.1.1.3、2模式
即文件末尾位置,所以要倒着移动!
# 文件内容:come朋友
with open('gaga', mode='rb') as src:
src.seek(-7, 2)
rea = src.read()
print(rea.decode('utf-8'))
# 执行pycharm得到结果
/home/sanxi/PycharmProjects/untitled1/venv/bin/python /home/sanxi/PycharmProjects/untitled1/test.py
朋友
4.1.1.4、tell
获取文件指针当前位置
with open('gaga', mode='rb') as src:
src.seek(-7, 2)
print(src.tell())
# 执行得到结果
4
4.2、seek()实现Linux tail -f
五、文件修改的两种方式
分两种:
- 文本编辑器常用的全新覆盖写
- 双刀流:实时读写
5.1、文本编辑器采用的方式
其实磁盘上的数据从来就没有修改这么一说,全都是覆盖写,一打开文件,文件内容被全部读到内存中,接下来改的都是内存里的数据,一点保存到磁盘,内存就会将这些数据直接全新写回源文件,因为速度太快,肉眼看到的好像就改了这个地方而已!
5.2、双刀流
同时打开两个文件,一行一行地读磁盘上的文件,接着一行一行地写入内存,然后快速删掉源文件,最后将新文件重命名为源文件!
这是源文件内容
come on
comehha
come667788
come来啊,互相伤害啊!
开始修改
import os
with open(r'/home/sanxi/Desktop/gaga.txt', mode='rt', encoding='utf-8') as log, open(r'gaga', mode='wt', encoding='utf-8') as open:
# log.seek(0, 2)
for line in log:
open.write(line.replace('come', 'sanxi'))
open.close()
os.remove('/home/sanxi/Desktop/gaga.txt')
os.rename('gaga', '/home/sanxi/Desktop/gaga.txt')
# import是引用别人封装好的功能
# 执行pycharm得到结果
这个看起来比较假,没有第一种方式那样直观,但是结果都是一样的!