zoukankan      html  css  js  c++  java
  • 009.Python之with管理与文件操作的其他方法

    一、文件操作模式补充

    (一)with上下文管理

    1.with是什么

    with关键字是python提供给我们的一个功能,用于帮助管理我们计算机的资源,提高计算机资源的利用效率,最终提高程序的运行效率。

    2.为什么要用with

    我们进行文件操作的时候,打开一个文件包含两部分资源,应用程序的变量f和操作系统打开的文件。在操作完毕一个文件的时候,必须把与该文件相关的这两部分资源全部回收,回收方法为:

    1、f.close() #回收操作系统打开的文件资源
    2、del f #回收应用程序级的变量
    

    其中del f 一定要发生在f.close()之后,否则就会导致操作系统打开的文件无法关闭,白白占用资源,而python自动的垃圾回收机制决定了我们无序考虑del f ,这就要求我们,在操作完毕文件后,一定要记住f.close()操作。但是这个操作常常有人会忘记,考虑到这一点,python提供了with关键字来帮我们管理上下文,解决忘记关闭 文件句柄f 的问题。

    3.怎么用with

    我们之前使用的文件操作方法是:

    1) 打开文件,由应用程序向操作系统发起系统调用open(...),操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给一个变量f
     f=open('a.txt','r',encoding='utf-8') # 默认打开模式就为r
     
    2) 调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作
     data=f.read()
     
    3) 向操作系统发起关闭文件的请求,回收系统资源
     f.close()
    

    使用了with之后,我们就可以简化掉第三步,并为我们提供了同时打开多个文件的功能:

    1) 在执行完子代码块后,with 会自动执行f.close():
    with open('a.txt','w') as f:
        pass 
    
    2) 可用用with同时打开多个文件,用逗号分隔开即可:
    with open('a.txt','r') as read_f,open('b.txt','w') as write_f:  
        data = read_f.read()
        write_f.write(data)
    

    (二)b模式

    1.t模式与b模式比较

    (1)t模式只能读取文本文件

    # 操作文件过程中,切记编码的问题!
    with open('a.txt',mode='rt') as f:  # 'a.txt'内容:你好呀
    哈哈哈
    hello
        data=f.read()
        print(data)  # 报错 UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 8: illegal multibyte sequence  所以我们需要注意字符编码的问题,指定编码类型!!
        print(type(data))
    
    with open('a.txt',mode='rt') as f:  # 'a.txt'内容:hello
        data=f.read()
        print(data)   # hello
        print(type(data))  # <class 'str'>  我们的文本文件读取,是以字符串为单位的。
    
    with open('a.jpg',mode='rt',encoding='utf-8') as f:
        data=f.read()
        print(data)  # UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
    # 使用t模式读取图片文件,会报错,并提示需要使用b模式读取
    
    # 图片<---------jpg-------二进制数
    # 字符<---------utf-8-------二进制数
    

    (2)b模式能用于读取所有文件

    with open('a.jpg',mode='rb') as f:
        data=f.read()
        print(data)   # b'xff...   一大串经过python修改过的二级制数据
        print(type(data))  # <class 'bytes'>
    
    with open('a.jpg', mode='rb') as f:
        data = f.read()
        print(data.decode("utf-8"))  # UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
    

    2.编写copy工具的两种方式

    方式一:一次性读取,如果文件过大,可能会造成内存溢出
    with open('a.jpg', mode='rb') as src_f, 
            open('b.jpg', mode='wb') as dst_f:
        data = src_f.read()
        print(data)  #  b模式二进制数
        dst_f.write(data)
    
    
    方式二:推荐使用,每次只读一行内容,资源压力小
    with open('a.jpg', mode='rb') as src_f, 
            open('b.jpg', mode='wb') as dst_f:
        for line in src_f: # line=文件中的1行内容
            dst_f.write(line)
    
    

    3.使用b模式copy文本文件

    1) 使用b模式copy文本文件
    with open('b.txt', mode='wb') as f:
        user = "张三"
        res=user.encode('utf-8')
        f.write(res)
    
    2) 使用t模式copy文本文件
    with open('b.txt', mode='wt', encoding="utf-8") as f:
        user = "张三"
        f.write(user)
    
    # 使用b模式虽然可以拷贝文本文件,但是操作过于复杂,最好直接使用t模式
    

    (三)+模式(了解)

    # r+ w+ a+ :可读可写
    #在平时工作中,我们只单纯使用r/w/a,要么只读,要么只写,一般不用可读可写的模式
    

    (四)文件操作的其他方法

    1.readlines()

    每次读取一行,并写入列表

    with open('b.txt', mode='rt', encoding='utf-8') as f:
        l = []
        for line in f:
            l.append(line)
            print(l)  # ['111
    '] / ['111
    ', '222
    '] / ['111
    ', '222
    ', '333
    '] / ['111
    ', '222
    ', '333
    ', '444
    ']
    
        l = f.readlines()  # 以上三行代码的操作,可以使用一行完成,直接输出结果
        print(l)  # ['111
    ', '222
    ', '333
    ', '444
    ']
    

    2.writelines()

    循环目标数据,按照单个元素循环写入

    with open('b.txt', mode='wt', encoding='utf-8') as f:
    1)  方式1 
    	f.write("1111
    2222
    333
    ")
    
    2)  方式2  
    	lines=["1111
    ","222
    ","333
    "]
    	for line in lines:
            f.write(line)
    
    3)  方式3
    	lines=["1111
    ","222
    ","333
    "]
        f.writelines(lines)
    # 以上三种方法都可以实现将这组数据写入文件,使用第三种最方便。
    

    3.name

    f.name 是获取文件的路径

    with open(r'b.txt', mode='wt', encoding='utf-8') as f:
        print(f.name) # b.txt  获取的是文件的路径    
    

    4.flush()

    # 强制刷新
    with open(r'b.txt', mode='wt', encoding='utf-8') as f:
        f.write('哈哈哈
    ')
        f.flush()  # 不使用flush的话,操作系统会按照系统规则,攒一波数据批量写入,但是使用flush的话,就可以强制写入硬盘,但不推荐使用,除非必要。
    

    (五)其他补充知识

    1.补充:字符编码知识

    user = "张三"
    
    # 编码操作:
    # 字符串===utf-8===》bytes
    res=user.encode("utf-8")
    print(res)  # b'xe5xbcxa0xe4xb8x89'
    print(type(res))  #  <class 'bytes'>
    
    # 基于网络发送数据(res)
    
    # 解码操作:
    # t模式是帮我们解码了
    # 字符<---------utf-8-------二进制数
    # bytes====》utf-8=====》字符串
    print(res.decode("utf-8"))  # 张三
    
    

    2.a模式应用场景:日志的切割

    我们在维护程序的时候,若不对日志文件进行管理,日志就会无线增大,所以我们常常在日志文件达到一定大小的时候,对日志文件进行切割。具体做法是将原日志文件重新命名,增加上时间标识,然后程序在找不到日志文件的情况下,会重新创建一个新的日志文件。

    3.rt模式下的理解易错点

    f=open('今日内容.txt',mode='rt',encoding='utf-8')
    print('第一次读'.center(50,'='))
    res1=f.read()
    print(res1)
    
    print('第二次读'.center(50,'='))
    res2=f.read()
    print(res2)
    
    f.close()
    
    # 以上程序,在第一次读操作的时候,已经将文件内容全部读取到,紧接着又进行了依次读取操作,但是这次读取内容是什么呢?实际是空的,因为第一次读取后,指针在文件的末尾,而文件未关闭或进行其他指针移动操作,所以指针位置不变,再次读取,将不会有任何内容被读出。
    
  • 相关阅读:
    【MFC】在CHtmlView中在同一窗口显示新打开页面
    【MFC】CHtmlView::GetSource中文乱码的问题
    【Win32】对指定进程进行禁音
    【MFC】在CHtmlView中准确判断页面加载完成
    【MFC】CHtmlView或WebBrowser禁止脚本错误提示
    【MFC】CDialogBar中按钮不可用
    【转载记录】Accessing Device Drivers from C#
    【源代码R3】移植一份LARGE_INTEGER转时间的代码
    Square Root of Permutation
    MySQL创建视图命令
  • 原文地址:https://www.cnblogs.com/huluhuluwa/p/13095558.html
Copyright © 2011-2022 走看看