python 文件操作2

发布时间:2018-02-25 10:07:15编辑:admin阅读(4087)

    继续讲解文件操作的其他内置方法


    读取文件句柄的指针

    指针,就是说,程序读取文件到哪一行了。

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.tell())

    执行输出 0

    默认是从0行开始读取的。


    读取一行,看下指针

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.tell())
    print(f.readline().strip())
    print(f.tell())

    执行输出

    0

    Somehow, it seems the love I knew was always the most destructive kind

    72


    最后一个,为什么是72呢?文件明明只有64行,而且readline()只会读取一行。

    因为tell()是根据字符串长度来计算的。


    read()方法不光可以读取整个文件,也可以读取指定的长度

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.tell())
    print(f.read(8))
    print(f.tell())

    执行输出

    0

    Somehow,

    8


    seek() 方法用于移动文件读取指针到指定位置。

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.tell())
    print(f.readline(8))
    print(f.tell())
    f.seek(0)
    print(f.tell())

    执行输出

    0

    Somehow,

    8

    0


    打印文件编码

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.encoding)

    执行输出 utf-8


    打印文件在内存中的编号

    print(f.fileno())

    执行输出 3

    操作系统会记录打开文件,记录的编号。python就是调用这个接口而已。


    打印文件名

    print(f.name)

    执行输出 Yesterday.txt


    判断文件指针是否可以移动

    print(f.seekable())

    执行输出 True

    比如Linux系统里面的tty文件,是不允许移动指针的。


    判断文件是否可读

    print(f.readable())

    执行输出 True


    判断文件是否可写

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.writable())

    执行输出 False

    因为是r模式


    flush() 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。

    一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。

    对于实时写入要求比较高的场景,可以用flush() 方法

    f = open("test.txt",'r',encoding="utf-8")
    f.write("hello\n")
    f.flush()


    在linux 上面yum安装的时候,有一个###进度条显示的

    flush()可以模拟进度条显示,代码如下:

    #!/usr/bin/env python
    # coding: utf-8
    __author__ = 'www.py3study.com'
    
    #导入模块
    import sys,time
    
    for i in range(10):
        #stdout表示标准输出,也就是屏幕输出。
        sys.stdout.write("#")
        #刷新缓冲区
        sys.stdout.flush()
        #等待0.1秒
        time.sleep(0.3)

    执行效果如下:

    jindu.gif


    判断文件是否关闭

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.closed)

    执行输出 False


    清空文件内容

    truncate() 方法用于截断文件,如果指定了可选参数 size,则表示截断文件为 size 个字符。 如果没有指定 size,则从当前位置起截断;截断之后 size 后面的所有字符被删除。

    f = open("Yesterday.txt",'a',encoding="utf-8")
    f.truncate()

    查看文件,发现内容全无


    truncate()也可以接参数

    f = open("Yesterday.txt",'a',encoding="utf-8")
    f.truncate(10)

    把歌词重新复制进去,执行程序

    查看文件内容

    Somehow, i


    发现保留了前10个字符串,后面的全部被清除了。


    读写模式,写入文件

    f = open("Yesterday.txt",'r+',encoding="utf-8")
    print(f.readline().strip())
    print(f.tell())
    f.write("---hello---\n")

    执行输出

    Somehow, it seems the love I knew was always the most destructive kind

    72

    查看文件,发现内容写入到最后一行了。


    写读模式,写入文件

    f = open("Yesterday.txt",'w+',encoding="utf-8")
    print(f.readline().strip())
    print(f.tell())
    f.write("---hello---\n")

    执行输出


    0

    查看文件,只有 

    ---hello---


    为啥只有一行呢?因为w表示创建一个新文件,文件内容被清空了。f.write写入了一行内容。


    先写3行,设置指针,再写入一行

    f = open("Yesterday.txt",'w+',encoding="utf-8")
    f.write("---hello---\n")
    f.write("---hello---\n")
    f.write("---hello---\n")
    print(f.tell())
    f.seek(10)
    print(f.tell())
    print(f.readline())
    f.write("---hello2---\n")
    f.close()

    执行输出

    39

    10

    -


    查看文件内容

    ---hello---

    ---hello---

    ---hello---

    ---hello2---


    从内容上来看,指针设置不生效,文件还是写入到最后一行了

    没有办法,根据指针修改。因为一旦这样,不想被修改的部分就会被覆盖。


    写读模式,一般很少用

    读写模式,还是比较常用的


    还有几种模式

    a+ 表示追加读写

    rb 二进制文件


    二进制文件,不允许传encoding参数,否则报错

    ValueError: binary mode doesn't take an encoding argument


    二进制模式,可以读取文件

    f = open("Yesterday.txt",'rb')
    print(f.readline())
    print(f.readline())
    print(f.readline())
    f.close()

    执行输出

    b'---hello---\r\n'

    b'---hello---\r\n'

    b'---hello---\r\n'


    前面的b 表示 二进制文件

    \n 变成了\r\n 这个是windows的换行符


    什么情况下,会用到二进制呢?

    1. socket网络传输

    2. FTP发送上传ISO镜像



    二进制写入模式

    f = open("Yesterday.txt",'wb')
    f.write("hello binary\n".encode())
    f.close()

    写入一个字符串时,必须要用encode()方法转换为二进制,才能写入文件

    执行,查看文件内容

    hello binary


    还是上面的歌词,我需要修改第8行的歌词

    就如舌尖上的雨露

    改成

    就如舌尖上的中国


    如果一次性将文件内容写入到内存中,遇到大文件时,程序就卡死了。

    那么程序的修改思路是这样的

    每次读取一行,并写入新文件。当读取的内容符合条件时,修改内容,并写入新文件,这样比较节省内存。


    f = open("Yesterday.txt",'r',encoding="utf-8")
    f_new = open("Yesterday.txt.bak",'w',encoding="utf-8")
    for line in f:
        if "雨露" in line:
            line = line.replace("雨露","中国")
        f_new.write(line)
    f.close()
    f_new.close()

    执行程序,查看Yesterday.txt.bak文件

    blob.png


    with语句


    为了避免打开文件后忘记关闭,可以通过管理上下文,即:

    with open('log','r') as f:
        pass

    如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。


    在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:

    with open('log1') as obj1, open('log2') as obj2:
        pass


    举个例子:

    打开文件,读取一行

    f = open("Yesterday.txt",'r',encoding="utf-8")
    print(f.readline().strip())
    f.close()

    等同于

    with open("Yesterday.txt",'r',encoding="utf-8") as f:
        print(f.readline().strip())


    由于写代码的时候,经常会忘记写f.close()。虽然程序执行完毕,会自动释放内存。

    如果碰到程序逻辑复杂的时候,不写f.close()就会造成内存浪费。

    所以推荐使用with方法来打开一个文件。


    上面改歌词的代码,可以改造成with方式

    with open("Yesterday.txt",'r',encoding="utf-8") as f,\
        open("Yesterday.txt.bak",'w',encoding="utf-8") as f_new:
        for line in f:
            if "雨露" in line:
                line = line.replace("雨露","中国")
            f_new.write(line)

    由于with 打开2个文件,代码太长了。根据python开发规范,一行代码不要超过80个字符。

    直接用\ 换行,这样代码看着不会那么长。


    执行效果和上面一样。with执行完之后,内存自动释放。

关键字