9、Python之文件操作进阶

Python入门 / 2020-10-28

一、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

截图录屏_选择区域_20201028232521.gif

五、文件修改的两种方式

分两种:

  • 文本编辑器常用的全新覆盖写
  • 双刀流:实时读写

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得到结果

截图录屏_选择区域_20201028234914.gif
这个看起来比较假,没有第一种方式那样直观,但是结果都是一样的!

世间微尘里 独爱茶酒中