zoukankan      html  css  js  c++  java
  • Python小白学习之路(二十)—【打开文件的模式二】【文件的其他操作】

    打开文件的模式(二)

    对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作
    (而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)

    rb:    以字节方式读文件
    wb:  以字节方式写文件
    ab:   以字节方式追加文件

    注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,所以不能指定编码

    1. rb

    #错误举例
    f = open ('test1.py', 'rb', encoding = 'utf -8')
    data = f.read()
    print(data)
    f.close()
    
    #执行结果:
    报错
    f = open ('test1.py', 'rb', encoding = 'utf-8')
    ValueError: binary mode doesn't take an encoding argument

    (以b方式打开时,因为读取到的内容是字节类型,所以不能指定编码方式,否则会报错)
    #正确
    f = open ('test1.py', 'rb')
    data = f.read()
    print(data)
    f.close()
    
    #执行结果:
    b"'hello'
    'xe5xb0x8fxe7x81xabxe9x94x85'
    '666'"

    test1.py中的内容如下:


    'hello'
    '小火锅'
    '666'

    分析该程序执行结果:


    1. python在windows操作系统下,换行符为在windows操作系统下,换行符为
    2. ‘字符串’-------encode-------》bytes
         bytes---------decode-------》‘字符串’

    所以,我们想让执行结果为字符串,可在print时做decode处理

    f = open ('test1.py', 'rb')
    data = f.read()
    print(data.decode('utf-8'))
    f.close()
    
    #执行结果:
    'hello'
    '小火锅'
    '666'


    2. wb

    #错误举例
    
    f = open ('test1.py', 'wb')
    f.write('hello')
    f.close()
    
    #执行结果:
    
    TypeError: a bytes-like object is required, not 'str'
    
    (以b方式写入时需要提供字节类型,所以不能写入字符串类型)
    #正确
    
    f = open ('test1.py', 'wb')
    f.write(bytes('hello
    小火锅', encoding = 'utf-8' ))
    f.close()

    3. ab

    #举例
    f = open ('test1.py', 'ab')
    f.write(bytes('hello
    小火锅
    ', encoding = 'utf-8' ))
    f.close()

    关于文件的其他操作介绍

    1. .encoding 读取文件打开时后的编码方式(即open时指定的编码方式)

    #举例
    
    f = open ('test1.py', 'w', encoding = 'GB2312')
    f.close()
    print(f.encoding)
    
    #执行结果:
    
    GB2312


    2. .closed 确定文件是否关闭

    #举例
    
    f = open ('test1.py', 'w', encoding = 'utf-8')
    f.close()
    print(f.closed)
    
    #执行结果:
    
    True

    3. .flush 刷新操作(将文件内容从内存刷到硬盘)

    4. .tell 读取光标所在位置

    补充:文件内光标移动

    一: read(3):

       1. 文件打开方式为文本模式时,代表读取3个字符

       2. 文件打开方式为b模式时,代表读取3个字节

    二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate


    test1中的内容
    aaa
    小火锅
    666

    #举例
    f = open ('test1.py', 'r', encoding = 'utf-8')
    print(f.tell())
    f.readline()
    print(f.tell())
    f.readline()
    print(f.tell())
    f.close()
    
    #执行结果:
    0
    5
    16
    #结果分析:
    第一个tell判断光标位置时候,光标在文件开头,即在位置0
    读取了一行之后,光标跑到文件第二行开头,但是在Windows操作系统,换行符为 
    ,占两个字节,而且tell光标移动以字节为单位,所以光标位置为 5
    读取了第二行之后,光标跑到了文件第三行开头,光标经历了三个汉字和换行符,在编码方式为 utf-8 时,走过了3*3+2=11个字节,所以光标位置为 16


    5. .seek 控制光标的移动

    #举例
    f = open ('test1.py', 'r', encoding = 'utf-8')
    f.seek(2) #光标从默认位置0开始,往后移动两个字节
    data = f.read()
    print(data) #打印光标后的内容
    f.close()
    
    #执行结果:
    a
    小火锅
    666

    如果,我将test1.py的内容改为

    小火锅
    aaa
    666

    再次执行上述程序

    #报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8f in position 0: invalid start byte

    原因:一个汉字在utf-8编码方式为3个字节,seek(2)移动两个字节,难道有神奇的功能将汉字劈开嘛,所以肯定会报错啊!

    关于seek的一些补充:

    seek有三种模式,分别为

    • 0模式 默认从0开始(不用指定)
    • 1模式 从上次相对位置开始
    • 2模式 从文件末尾开始seek(第一个参数需要为负数)
    举例:
    f = open ('test1.py', 'r', encoding = 'utf-8')
    f.seek(3)
    print(f.tell())
    f.seek(9)
    print(f.tell())
    f.close()
    
    #执行结果
    3
    9
    f = open ('test1.py', 'rb')
    f.seek(3,1)
    print(f.tell())
    f.seek(10,1)
    print(f.tell())
    f.close()
    
    #执行结果
    3
    13
    f = open ('test1.py', 'rb')
    f.seek(-3,2) #seek 在模式 2 时,第一个参数为负数
    print(f.tell())
    print(f.read())
    f.close()
    
    #执行结果
    18
    b'6
    '

    任务:应用:打开一个日志文件,并且读取最新日志(核心:倒着读文件内容)

    日志文件内容如下:
    2018/11/20 aaa 上网听歌
    2018/11/20 bbb 上网网购
    2018/11/20 ccc 上网学习

    #方法一
    f = open('日志文件', 'rb')
    data = f.readlines() #将日志文件的内容以列表形式读到内存中
    print(data[-1].decode('utf-8')) #以切片方式读取列表中最后一个元素,即文件最后一行内容
    
    #执行结果
    2018/11/20 ccc 上网学习
    #方法二
    f = open('日志文件', 'rb')
    for i in f: #文件循环方式
        offs = -10 #设置初始偏移量 
        while True: #设置一个死循环来读取文件的最后一行内容,读取到break 
            f.seek(offs, 2) #seek模式2,光标倒着移动
            data = f.readlines() #以列表形式读取光标后的内容
            if len(data) > 1: #如果该列表长度大于1,说明光标移动到最后一行之前,最后一行内容已被读出,break,反则最后一行内容还未全部读出,将偏移量扩大,直到独处最后一行全部内容
              print('文件最后一行:%s'%(data[-1].decode('utf-8')))
              break
            offs *= 2
    
    #执行结果
    文件最后一行:2018/11/20 ccc 上网学习                        

    方法一看着简单,但是方法一需要将日志文件的内容一列表形式全部读到内存中,占用较多内存
    方法二的思想就是我用最后一行内容,我倒着读,只关注我想得到的信息

    6. .truncate 截取文件内容(实质为文件内容的改写,所以在 open 文件时,需要设置正确的打开文件的模式)

    举例:
    
    f = open('日志文件', 'r+',encoding = 'utf-8')
    data = f.truncate(8)
    print(data)

    注意:

    • 打开方式不可以是r(报错,实质为文件的改写)
    • 打开方式不可以是w w+(这两个模式将内容全部删除,所以截取不到任何内容)
  • 相关阅读:
    pycharm运行html文件报404错误
    css3 鼠标悬浮动画效果
    子代选择器和后代选择器的区别
    前端入门
    爬虫Scrapy框架
    BeautifulSoup
    爬虫之selenium使用
    爬虫之BeautifulSoup
    urllib模块
    爬虫基础
  • 原文地址:https://www.cnblogs.com/guoruxin/p/10008904.html
Copyright © 2011-2022 走看看