python文件处理

发布时间:2019-09-18 07:24:14编辑:auto阅读(1546)

    文件操作介绍

    python中的都是用 open() 函数,调用 open() 函数,应用程序会发起系统调用 open(...) ,进而对文件完成操作~。以下示例均在 python3 环境中完成~

    读取文件

    简单读取

    读取文件示例:

    f = open(file='/Users/luyi/tmp/abc', mode='r', encoding='utf-8')
    data = f.read()       # 读取文件中所有数据
    print(data)             # 打印文件内容
    f.close()                 # 关闭操作系统级打开的文件

    open() 函数参数说明:

    file:指定文件路径
    mode:指定打开文件的模式,r 表示只读模式,还有很多其他模式,下面会依次介绍
    encoding:指定从文件中读取的数据使用什么解码标准(decode),解码后以unicode的形式存放到内存中~。注意:若不指定encoding,打开文件的默认编码就是操作系统的默认编码,简体中文版的windows是gbk,linux下是utf-8。以什么编码存放,就应该以什么编码读取~

    读取文件操作的注意点:
    1)读取动作完成之后,需要关闭操作系统级打开的文件(f.close())
    2)回收应用程序级的变量(del f)
    Tip:f 变量没有引用之后,python垃圾回收机制会自动回收 f 变量,无需手动进行。但是f.close()必须手动完成,否则会持续占用系统资源,直至程序运行结束~

    也有一种方式 不需要手动关闭系统级资源

    with open() as f:
        pass
    
    # 将上述代码进行调整
    with open(file = '/Users/luyi/tmp/abc', mode = 'r', encoding = 'utf-8') as f:
        data = f.read()
        print(data)

    Tip:with段代码运行结束,系统级打开的文件会自动被关闭~

    with 还可以同时打开多个文件,如下示例实现了文件的文件的逐行复制,其中涉及到的方法下面会介绍:

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'r', encoding='utf-8') as read_file, open(file = '/Users/luyi/tmp/cde.txt', mode = 'w', encoding='utf-8') as write_file:
        for line in read_file:
            write_file.write(line)

    在读取文件时,若不清楚正在打开的文件是什么编码,可以使用chardet模块探测文件的编码方式

    import chardet
    result = chardet.detect(open('/Users/luyi/tmp/abc.txt', mode='rb').read())
    print(result)
    
    结果输出:
    {'encoding': 'utf-8', 'confidence': 0.87625, 'language': ''}

    上述示例中,使用 'rb' 模式打开文件,即以只读,且以字节为单位打开文件。非文本文件只能使用 b 模式打开,因为文件本身就是以字节的形式存放在存储设备上的。文本文件可以使用字节模式打开,也可以 以本文模式打开(默认),图片格式的文件(jpg,png...)、视频音频格式文件(mp3、mp4、avi...)则只能以字节模式打开。

    当文本文件使用字节模式打开时,open函数中不能使用 encoding 参数,若要转成unicode,只能现将数据读到内存,然后手动decode~

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'rb', encoding = 'utf-8') as f:
        print(f.read())
    
    # open中使用 encoding参数,会直接抛出错误信息
    ValueError: binary mode doesn't take an encoding argument
    
    #############
    
    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'rb') as f:
        data = f.read()
        print(data)                           # 原样输出内容
        print(data.decode('utf-8'))  # 解码后输出文本内容
    
    输出结果:
    b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8ckitty\n'
    你好,kitty

    循环文件

    f = open("abc.txt",'r',encoding="utf-8")
    data = f.read()

    使用这种方式读取文件,会一次性将文件中所有的数据读到内存中,如果文件很大,这会给内存造成很大的压力,这并不是一种合理的读取文件方式。这时候可以逐行获取数据~

    # 使用 readline() 仅读取文本的一行内容,光标从文件的开头移动到一行的末尾(只读一行,遇到\r 或者 \n 为止),然后读物第二行
    with open(file = '/Users/luyi/tmp/def.txt', mode = 'r', encoding='utf-8') as f:
        data = f.readline()         # 仅读取一行
        print(data)
    
    # 使用 while 循环遍历文件
    with open(file = '/Users/luyi/tmp/def.txt', mode = 'r', encoding='utf-8') as f:
        line = f.readline()
        while line:                   # 当 line 不为None,继续读取文件
            print(line, end='')    # print() 自带换行功能,line中已有'\n',print不用再换行,所以加上参数end=''
            line = f.readline()
    
    # 使用 for 循环遍历 f 变量也是逐行读取文件内容,与 readline() 类似。这里其实内部调用了 f 变量的next()方法,逐行迭代文件对象,这种方式的遍历貌似比 readline() 要来的简单明了。
    with open(file = '/Users/luyi/tmp/def.txt', mode = 'r', encoding='utf-8') as f:
        for line in f:
            print(line, end='')

    Tip:在调用next()方法时,不能同时调用 tell() 方法获取文件光标位置

    和 readline() 功能类似的还有个 readlines() ,readlines()会将文件的内容一次性获取,并存储为列表,文件每一行内容为列表的一个元素~

    with open(file = '/Users/luyi/tmp/def.txt', mode = 'r', encoding='utf-8') as f:
        line = f.readlines()
        print(type(line))
        print(line)
    
    结果输出:
    <class 'list'>
    ['1.aaaaaaaaa\n', '2.bbbbbbbbb\n', '3.ccccccccc\n', '4.ddddddddd\n', '5.eeeeeeeee\n', '6.fffffffff\n']

    写文件

    python写文件,同样使用open(),模式使用 'w'(只写),'wb'(二进制写),'w+'(可读可写)~

    直接写

    f = open(file = '/Users/luyi/tmp/abc.txt', mode = 'w', encoding = 'utf-8')
    f.write('你好~~,hello')
    f.close()       # 同样需要注意,关闭系统级别的资源

    open() 参数说明:

    file:指定文件路径,若该目录下文件不存在,会创建,若文件存在,直接覆盖;若目录不存在,抛出错误
    mode='w':指定为只写模式
    encoding:指定写入到文件时,使用的编码标准,即将 内存中 unicode 格式的数据 按照指定编码标准编码后进行存储(这里是 encoding 过程,和read相反)

    同样可以使用 with open() 方式代替:

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'w', encoding = 'utf-8') as f:
        f.write('你好!!,hello')

    二进制写

    二进制写 的模式为 'wb',当指定 mode='wb' ,写入数据时必须传入字节类型的数据(bytes类型),且需要手动添加换行符(\n)

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'wb') as f:
        f.write('你好~~,hello'.encode('utf-8'))

    Tip:这里由于是'wb'模式,write()函数中需要传入bytes类型的数据,直接使单引号或双引号包含的数据是 str 类型,str 类型的数据 encode 之后,返回的是 bytes类型,或者也可以使用 b'' ~

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'wb') as f:
        f.write(b'abc')          # bytes 类型只能包含 ASCII 码字符

    同时写入多行使用writelines()函数

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'w', encoding='utf-8') as f:
        f.writelines(['111111\n', '222222\n', '333333\n'])    # 需要自己添加换行符
    
    # wb模式
    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'wb') as f:
        f.writelines([bytes('你好\n'.encode('utf-8')), 'kitty\n'.encode('utf-8')])

    Tip:f.flush() 可立刻将文件内容从内存刷到磁盘
    注意点:当以 'w' 、'wb'、'w+'(写读模式,很少用) 模式打开文件时,在打开文件的同时会将文件内容清空~

    读写模式

    打开文件模式还有读写模式,打开后可进行读写操作,即 mode='r+';

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'r+', encoding='utf-8') as f:
        print(f.read())
        f.write('你好~~,hello')

    追加文件

    打开文件时,若使用模式 “a” 或 “ab” ,则只能对文件进行追加,即:在原来内容的尾部追加内容~

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'a', encoding='utf-8') as f:
        f.write('aaaaaaa\n')
        f.write('vvvvvvv\n')
    
    文件内容:
    你好
    kitty
    aaaaaaa
    vvvvvvv

    文件操作的各种模式说明

    操作文件的模式列举

    模式 说明
    'r' 读模式
    'w' 写模式
    'a' 追加模式
    'b' 二进制模式
    't' text 模式(默认)
    '+' 同时读写某个文件
    'x' 只写模式,文件不存在 自动创建,文件原先就存在则报错

    除了上述几个模式,还有以上模式的各种组合~
    常用的模式还有:
    rb','wb','ab' # 非文本文件,只能使用 'b' 模式打开
    'r+','w+','a+' # 都表示可读写,但是注意了 'w+' 模式打开文件,会首先清空文件,所以一般模式 'w+' 很少用,使用模式 'a+' 时,光标会直接跳到文件的最后,所以之前的内容读不到~

    针对文件的其他操作

    其他文件操作的常用函数:

    def writable(self, *args, **kwargs): # real signature unknown
            判断文件是否可写
    
    def readable(self, *args, **kwargs): # real signature unknown
            判断文件是否可读
    
    def fileno(self, *args, **kwargs): # real signature unknown
            返回文件句柄在内核中的索引值,做IO多路复用时可以用到
    
    def seek(self, *args, **kwargs): # real signature unknown
            移动光标移到指定位置,注意这里移动光标的单位是字节
    
    def seekable(self, *args, **kwargs): # real signature unknown
            判断文件是否可进行 seek 操作
    
    def tell(self, *args, **kwargs): # real signature unknown
            返回当前文件操作光标位置 
    
    def truncate(self, *args, **kwargs): # real signature unknown
            按指定长度截断文件,经个人测试 python3中的 truncate 方法貌似已经失效

    在对文件操作的过程中,光标会不断移动,例如readline()方法读取一行信息后,光标会移动至当前行的末尾,writeline()光标也会移动至当前行末尾(写过程貌似光标一直在末尾)~

    光标移动的单位和文件被打开的模式相关,若文件以文本模式打开时,read(5) 会使光标向后移动5个字符;若文件以非文本模式打开('b'模式),则 read() 会向后移动5个字节。seek函数不管模式是什么,光标移动的单位都是字节~

    例如文本内容如下:

    123456789
    abcdefghi

    code:

    with open(file = '/Users/luyi/tmp/abc.txt', mode = 'r+', encoding='utf-8') as f:
        f.seek(5)
        print(f.readline())
        print(f.tell())        # 输出当前光标位置
    
    结果输出:
    6789
    
    10

    seek 方法可接受2个参数:

    fileObject.seek(offset[, whence])

    offset:光标的偏移量,以字节为单位
    whence:可选参数,默认值为 0。表示要从哪个位置开始偏移;0 代表从文件开头开始偏移,1 代表从当前位置开始偏移,2 代表从文件末尾开始偏移。

    .................^_^

关键字

上一篇: MorningDiary(Python版

下一篇: apache+mod_python