zoukankan      html  css  js  c++  java
  • 文件操作

    一、文件操作

       使⽤python来读写⽂件是非常简单的操作. 我们使用open()函数来打开一个文件, 获取到⽂文 件句句柄. 然后通过⽂文件句句柄就可以进行各种各样的操作了了. 根据打开方式的不同能够执行的操 作也会有相应的差异.     打开文件的⽅方式: r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b 默认使⽤用的是r(只读)模式 

      系统对文件的各种操作:

      1,将原文件读取到内存。
      2,在内存中进行修改,形成新的内容。
      3,将新的字符串写入新文件。
      4,将原文件删除。
      5,将新文件重命名成原文件。

    二、只读操作(r,rb, r+,r+b)

    f = open("护⼠少妇嫩模.txt",mode="r", encoding="utf-8") 
    content = f.read()       # 在这里要记住,在r模式下encoding 表示解码,在w情况下,是编码
    print(content) 
    f.close()
    
    # 需要注意encoding表⽰示编码集. 根据⽂文件的实际保存编码进⾏行行获取数据, 对于我们⽽而⾔言. 更更 多的是utf-8.   
    rb. 读取出来的数据是bytes类型, 在rb模式下. 不能选择encoding字符集. 但是涉及到需要解码或则编码是还是需要encoding, 
    
    
    f = open("护⼠少妇嫩模.txt",mode="rb" ) 
    content = f.read() 
    print(content) 
    f.close() 
    #结果: b'xe6xafx85xe5x93xa5, xe5xa4xaaxe7x99xbd, wuse
    xe5x91xb5xe5x91xb5
    xe6x97xa5xe5xa4xa9'
    
    
     rb的作⽤用: 在读取非⽂本⽂件的时候. 比如读取MP3. 图像. 视频等信息的时候就需要⽤用到 rb. 因为这种数据是没办法直接显⽰示出来的.  在后⾯面我们⽂文件上传下载的时候还会⽤用到. 还有.
    我们看的直播. 实际上都是这种数据.

       一般格式: f =open(’文件名(路径)', mode='模式',encoding ='编码方式')特殊格式: with open(’文件名(路径)', mode='模式',encoding ='编码方式') as f:

    文件操作流程:打开一个文件(),产生一个文件句柄,对文件句柄进行操作,关闭文件

        绝对路径和相对路径:

          1. 绝对路径:从磁盘根⽬录开始⼀一直到文件名. 2. 相对路路径:同⼀个文件夹下的⽂件. 相对于当前这个程序所在的⽂件夹⽽而⾔言. 如果在同 一个⽂件夹中. 则相对路径就是这个⽂件名. 如果在上一层⽂件夹. 则要../  (更推荐大家使用相对路径,因为我们在把程序拷贝时,直接把项目拷贝过去就好,不用拷贝C盘等其他盘)

    读取的方法(r,r+,rb):

      read()将文件的内容全部读取出来, 弊端:相当占内存,如果文件过大,容易导致内存崩溃

    f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 
    content = f.read() 
    print(content)   #结果: 友谊地久天长, 爱一点, 可惜我是⽔瓶座 一⽣生中最爱
    
    read(n)可以读取n个字符,需要注意的是,如果再次读取,那么将从光标位置读取,如果是rb模式,则是读取n个字节
    
    f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 
    content = f.read(3) 
    content2 = f.read(3) 
    print(content) 
    print(content2)    # 结果: 友谊地 久天⻓长
    
    
    readline() ⼀次读取⼀行数据, 注意: readline()结尾, 注意每次读取出来的数据都会有⼀ 个
     所以呢. 需要我们使⽤用strip()⽅方法来去掉
    或者空格
    readline(n) 当有参数n时,则时读取一行的开头的前n个字:
    readlines() 将每一⾏形成一个元素, 放到⼀个列表中. 将所有的内容都读取出来. 所以 也是. 容易易出现内存崩溃的问题.不推荐使⽤,形成一个列表
    
    我们来看看:
    with open('a.txt', 'r', encoding='utf-8') as f:
        s = f.read()
        for i in s:
            print(i)     # 这个运行的结果是,文件中的每一个字符为一行,说明read的结果是生成将每一个字符添加到一个列表中
    
    with open('a.txt', 'r', encoding='utf-8') as f:
        a = f.readlines()
        for i in a:
            print(i)      # 而这个结果是分别打印每一行的文字,说明readlines()的结果是将每一行加到一个列表中
    
    with open('a.txt', 'r', encoding='utf-8') as f:
        s = f.read()
        for i in s:
            print(i)
        a = f.readlines()
        for i in a:
            print(i)  # 这样的结果是以每一个字符读取换行,因为当下一次循环时,光标已经在末尾了

    from collections import Iterable,Iterator
    print(isinstance(open('a','w'),Iterable))  #True
    print(isinstance(open('a','w'),Iterator)) # True  所以文件句柄是个可迭代的,迭代器

    循环读取:
    f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 
    for line in f:    
        print(line.strip())

    三、写模式(w,wb, w+b,w+):

      写的时候注意. 如果没有文件. 则会创建文件, 如果⽂件存在. 则将原件中原来的内容删除, 再 写入新内容 

    f = open("⼩小娃娃", mode="w", encoding="utf-8") 
    f.write("⾦⽑狮王") 
    f.flush()    # 刷新. 养成好习惯 
    f.close()
    
    试试读能读吗?
    f = open("⼩娃娃", mode="w", encoding="utf-8") 
    f.write("金⽑狮王")
    f.read()    # not readable 模式是w. 不可以执行读操作 
    f.flush() 
    f.close()
    
    wb模式下. 可以不指定打开文件的编码. 但是在写文件的时候必须将字符串转化成utf-8的 bytes数据
    f = open("小娃娃", mode="wb") 
    f.write("⾦毛狮王".encode("utf-8"))   # 要注意再写的时候一定要写编码的格式
    f.flush() 
    f.close()
    
     rb, wb, ab, bytes如果处理的是非文本文件, mode里如果有b. encoding就不能给了(以下时复制粘贴图片的底层操作)
    f = open("c:/pdd.jpg", mode="rb") # 这里不能写encoding
    e = open("e:/pdd.jpg", mode="wb")
    for line in f: # 从c盘读取 line你是不知道读取了多少数据的
        e.write(line)   # 写入到e盘
    f.close()
    e.flush()
    e.close()

    四、追加(a, ab, a+b,a+)

      在追加模式下. 我们写入的内容会追加在⽂件的结尾,相当于在这种模式下,打开后光标默认在尾部.

    f = open("⼩小娃娃", mode="a", encoding="utf-8") 
    f.write("麻花藤的最爱") 
    f.flush() 
    f.close()          # 正常的读取之后, 写在结尾

    五、读写模式(r+,r+b)

      对于读写模式. 必须是先读. 因为默认光标是在开头的. 准备读取的. 当读完了之后再进行写入. 我们以后使⽤用频率最高的模式就是r+ 

    f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
    content = f.read() 
    f.write("麻花藤的最爱") 
    print(content) 
    f.flush() 
    f.close()   # 结果: 正常的读取之后, 写在结尾
    
    错误示范:
    f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
    f.write("哈哈") 
    content = f.read() 
    print(content) 
    f.flush() 
    f.close()     # 结果: 将开头的内容改写成了了"哈哈", 然后读取的内容是后⾯面的内容,因为光标的位置

    六、写读(w+ ,w+b)

      先将所有的内容清空,然后写入。最后读取,但是读取的内容时空的,不常用

    f = open("⼩小娃娃", mode="w+", encoding="utf-8") 
    f.write("哈哈") 
    content = f.read() 
    print(content) 
    f.flush() 
    f.close()    #  有人会说. 先读不就好了么? 错. w+ 模式下, ⼀开始读取不到数据. 然后写的时候再将原来的内容清空. 所以, 很少用. 

    七、追加读(a+)

       a+模式下, 不论先读还是后读. 都是读取不到数据的. 除非seek()光标位置

    f = open("⼩小娃娃", mode="a+", encoding="utf-8") 
    f.write("⻢马化腾") 
    content = f.read() 
    print(content) 
    f.flush() 
    f.close()   # 还有⼀些其他的带b的操作. 就不多赘述了. 就是把字符换成字节. 仅此⽽而已

    重要的方法:

      1、seek(n) 光标移动到n位置, 注意, 移动的单位是byte. 所以如果是UTF-8的中⽂部要是3的倍数. 通常我们使用seek都是移动到开头或者结尾.

      移动到开头: seek(0)

      移动到结尾: seek(0,2)

      seek的第⼆个参数表示的是从哪个位置进行偏移(初始位置), 默认是0, 表示开头, 1表⽰当前位置, 2表示结尾,seek(偏移度,位置)

      2、 tell() 使⽤用tell()可以帮我们获取到当前光标在什么位置

    f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
    f.seek(0)   # 光标移动到开头 
    content = f.read()  # 读取内容, 此时光标移动到结尾
    print(content) 
    f.seek(0)   # 再次将光标移动到开头 
    f.seek(0, 2)    # 将光标移动到结尾 
    content2 = f.read()  # 读取内容. 什什么都没有 
    print(content2)
     
    f.seek(0)   # 移动到开头 
    f.write("张国荣")  # 写⼊入信息. 此时光标在9  中⽂文3 * 3个 = 9 
    print(f.tell())  # 光标位置9 
    f.flush() 
    f.close()

      3. truncate() 截断⽂件  使用的是光标f = open("⼩娃娃", mode="w", encoding="utf-8"

    f.write("哈哈")   # 写入两个字符 
    f.seek(3)   # 光标移动到3, 也就是两个字中间 
    f.truncate()    # 删掉光标后⾯面的所有内容 
    f.close()
    
    f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
    content = f.read(3)  # 读取12个字符 
    f.seek(4) 
    print(f.tell()) 
    f.truncate()    # 后面的所有内容全部都删掉 
        # print(content) 
    f.flush() 
    f.close()
    注意事项:
     
    #log.txt 文件内容是‘哈哈,我是谁和谁’
    f = open('log.txt',encoding='utf-8',mode='r+')
    f.truncate(6)         # 运行结果是 哈哈   对文件进行修改
    content = f.read()   # 这里把文件加载到内存中,读取
    print(content)
    f.close()
     
    类似的情况却不一样:
    f = open('a.txt',encoding='utf-8',mode='r+')
      # f.truncate(6)
    content = f.read(3)    #把a.txt的内容全部加载到内存中,utf-8,三个字节是一个字符,读取后光标在‘哈’后面
    print(content)     # 运行的结果是‘哈哈,’
    f.truncate(3)         #在源文件中进行写,也就是执行后源文件变成了一个字,‘哈’,但是对加载到内存的read()没有影响
    print(f.read())        #这里运行的结果是 ”我是谁和谁“ 所以不是读取truncate后的文件 ,读取的是加载在内存的文件
    f.close()
     

      注意事项:

      深坑请注意: 在r+模式下. 如果读取了内容. 不论读取内容多少. 光标显示的是多少. 再写入 或者操作文件的时候都是在结尾进行的操作. 所以如果想做截断操作. 记住了. 要先挪动光标. 挪动到你想要截断的位置. 然后再进行截断 关于truncate(n), 如果给出了n. 则从开头进行截断, 如果不给n, 则从当前位置截断. 后⾯的内容将会被删除

    八.修改文件以及另一种打开方式:

          ⽂文件修改: 只能将⽂文件中的内容读取到内存中, 将信息修改完毕, 然后将源⽂文件删除, 将新 ⽂文件的名字改成老⽂文件的名字. 

    # 第一种修改方式:
    import os
    with open("⼩小娃娃", mode="r", encoding="utf-8") as f1,     
        open("⼩小娃娃_new", mode="w", encoding="UTF-8") as f2:    
             content = f1.read()    
             new_content = content.replace("冰糖葫芦", "⼤大⽩白梨梨") 
    
    f2.write(new_content) os.remove("⼩小娃娃")    # 删除源⽂文件     os.rename("⼩小娃娃_new", "⼩小娃娃")     # 重命名新⽂文件   
    
    #但是以上一种方法有弊端,因为其时一次性讲整个文件读入内存,若文件过大会崩溃 
    
    
    #推荐以下方法:
    with open("⼩小娃娃", mode="r", encoding="utf-8") as f1,     
        open("⼩小娃娃_new", mode="w", encoding="UTF-8") as f2:    
           for line in f1:        
          new_line = line.replace("⼤大⽩白梨梨", "冰糖葫芦")
            
    f2.write(new_line) 
    os.remove("⼩小娃娃")    # 删除源⽂文件 
    os.rename("⼩小娃娃_new", "⼩小娃娃")     # 重命名新⽂文件             

     练习题:

    1.文件a1.txt内容(升级题)
    
    序号     部门      人数      平均年龄      备注
    1       python    30         26         单身狗
    2       Linux     26         30         没对象
    3       运营部     20         24         女生多
    .......
    
    通过代码,将其构建成这种数据类型:
    [{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'},
    ......]
    
    l1 = []
      with open('a2.txt', encoding='utf-8') as f1:
            # 读取第一行,去除空格,使用空格切割成列表
          list_name = f1.readline().strip().split()
            # 从第二行开始读取,因为读取一行之后,光标自动移动到下面一行。
            # 所以for循环不会读取到第一行
          for i in f1:
              dic = {}
                # 去除空格,以空格切割成列表
              i = i.strip().split()
                # 遍历i
             for j in range(len(i)):
                    # 添加字典, list_name[j]表示key, i[j]表示value,比如'序号': '1'
                  dic[list_name[j]] = i[j]
                # 添加到列表中
              l1.append(dic)
    
    print(l1)
    
    
    2.文件a1.txt内容(升级题)
    
    name:apple price:10 amount:3 year:2012
    name:tesla price:100000 amount:1 year:2013
    .......
    
    通过代码,将其构建成这种数据类型:
    [{'name':'apple','price':10,'amount':3},
    {'name':'tesla','price':1000000,'amount':1}......]
    并计算出总价钱。
    
    li = []
    with open('a11.txt', 'r', encoding='utf-8') as f:
        for i in f:
            a = i.strip().split(' ')
            dic = {}
            for i in a:
                b = i.split(':')
                if b[1].isdigit():
                    dic[b[0]] = int(b[1])
                else:
                    dic[b[0]] = b[1]
    
            li.append(dic)
    print(li)
    sum = 0
    for i in range(len(li)):
        sum +=li[i]['price'] * li[i]['amount']
    
    # print(li)
    print('总计消费%d'%sum)
    1、缓存机制和小数据池:
        
        不同代码块的缓存机制:
        Python在执行同一个代码块的初始化对象的命令时,会检查是否其值是否已经存在,如果存在,会将其重用。换句话说:执行同一个代码块时,遇到初始化对象的命令时,他会将初始化的这个变量与值存储在一个字典中,在遇到新的变量时,会先在字典中查询记录,如果有同样的记录那么它会重复使用这个字典中的之前的这个值。所以在你给出的例子中,文件执行时(同一个代码块)会把i1、i2两个变量指向同一个对象,满足缓存机制则他们在内存中只存在一个,即:id相同。
    小数据池:
        Python自动将-5~256的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象。python会将一定规则的字符串在字符串驻留池中,创建一份,当你将这些字符串赋值给变量时,并不会重新创建对象, 而是使用在字符串驻留池中创建好的对象。其实,无论是缓存还是字符串驻留池,都是python做的一个优化,就是将~5-256的整数,和一定规则的字符串,放在一个‘池’(容器,或者字典)中,无论程序中那些变量指向这些范围内的整数或者字符串,那么他直接在这个‘池’中引用,言外之意,就是内存中之创建一个。
    
    2、编程题:
    有文件t1.txt里面的内容为:(5分)
        id,name,age,phone,job
        1,alex,22,13651054608,IT
        2,wusir,23,13304320533,Tearcher
        3,taibai,18,1333235322,IT
    
    利用文件操作,将其构造成如下数据类型。
    [{'id':'1','name':'alex','age':'22','phone':'13651054608','job':'IT'},......]
    
    l=[]
    with open('t1.txt','r',encoding = 'utf-8') as f:
        li = f.readline().strip().split(',')
        for i in f:
            lst = i.strip().split(',')
            for i in li:
                dic= dict([(li[0],lst[0]),(li[1],lst[1]),(li[2],lst[2]),(li[3],lst[3]),(li[4],lst[4])])
                l.append(dic)
    print(l)
    
    车牌区域划分,给出一下车牌和地点信息对照,请根据车牌信息,分析出各省的车牌持有数量。
        cars = ['鲁A32444', '鲁B12333', '京B8989M', '黑C49678', '黑C46555', '沪B25041', '黑C34567']
        locations = {'': '上海', '': '北京', '': '黑龙江', '': '山东', '': '湖北', '': '湖南'}(6分)
        最终形成这样的数据:{'山东': 2, '黑龙江': 3, '北京': 1, '上海': 1}
    
    法一:
    result = {}
    for car in cars:
       result[locations[car[0]]] = result.get(locations[car[0]], 0) + 1
    print(result)
    
    法二:
    for i in cars:
       if locations[i[0]]  not in li:
           li[locations[i[0]]] = 1
       else:li[locations[i[0]]] += 1
    print(li)
    
    
    按要求完成下列转化。(8分)
    list3 = [
        {"name": "alex", "hobby": "抽烟"},
        {"name": "alex", "hobby": "喝酒"},
        {"name": "alex", "hobby": "烫头"},
        {"name": "alex", "hobby": "Massage"},
        {"name": "wusir", "hobby": "喊麦"},
        {"name": "wusir", "hobby": "街舞"},
    ]
    list4 = [
        {"name": "alex", "hobby_list": ["抽烟", "喝酒", "烫头", "Massage"]},
        {"name": "wusir", "hobby_list": ["喊麦", "街舞"]},
    ]
    将list3 这种数据类型转化成list4类型,你写的代码必须支持可拓展,
    比如list3 数据在加一个这样的字典{"name": "wusir", "hobby": "溜达"},    你的list4{"name": "wusir", "hobby_list": ["喊麦", "街舞", "溜达"],
    或者list3增加一个字典{"name": "太白", "hobby": "开车"},
    你的list4{"name": "太白", "hobby_list": ["开车"],无论按照要求加多少数据,你的代码都可以转化.如果不支持拓展,则4分,支持拓展则8分.
    
    list3 = [
        {"name": "alex", "hobby": "抽烟"},
        {"name": "alex", "hobby": "喝酒"},
        {"name": "alex", "hobby": "烫头"},
        {"name": "alex", "hobby": "Massage"},
        {"name": "wusir", "hobby": "喊麦"},
        {"name": "wusir", "hobby": "街舞"},
    ]
    
    dic ={}
    for i in list3:
        if i['name'] not in dic:
             dic[i['name']] = {'name':i['name'],'hobby_list':[i['hobby']]}
        else:
             dic[i['name']]['hobby_list'].append(i['hobby'])
    list4 = list(dic.values())
    print(list4)
    第一次考试总结
  • 相关阅读:
    创建逻辑卷LVM以及swap分区
    Linux下命令别名配置
    vim多行注释与删除
    Linux下parted分区超过2TB硬盘-分区格式化
    scp命令限速远程拷贝
    tar命令加密压缩/解密解压
    centos下dnsmasq安装与配置
    Mac OS: xcrun: error: invalid active developer path, missing xcrun
    C/C++编译器GCC:GNU Compiler Collection
    es分页查询限制的问题
  • 原文地址:https://www.cnblogs.com/double-W/p/9440888.html
Copyright © 2011-2022 走看看