zoukankan      html  css  js  c++  java
  • 文件处理

    一 文件操作

    注操作文件的流程:

    #1. 打开文件,得到文件句柄并赋值给一个变量
    #2. 通过句柄对文件进行操作
    #3. 关闭文件

     f=open('a.txt','r')的过程分析

    #1、由应用程序向操作系统发起系统调用open(...)
    
    #2、操作系统打开该文件,并返回一个文件句柄给应用程序
    
    #3、应用程序将文件句柄赋值给变量f

    强调!!!

    #强调第一点:
    打开一个文件包含两部分资源:操作系统级打开的文件+应用程序的变量。在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:
    1、f.close() #回收操作系统级打开的文件
    2、del f #回收应用程序级的变量
    
    其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,
    而python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close()
    
    虽然我这么说,但是很多同学还是会很不要脸地忘记f.close(),对于这些不长脑子的同学,我们推荐傻瓜式操作方式:使用with关键字来帮我们管理上下文
    with open('a.txt','w') as f:
        pass
     
    with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
        data=read_f.read()
        write_f.write(data)
    
    强调第一点:资源回收
    #强调第二点:
    f=open(...)是由操作系统打开文件,那么如果我们没有为open指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。
    这就用到了上节课讲的字符编码的知识:若要保证不乱码,文件以什么方式存的,就要以什么方式打开。
    
    f=open('a.txt','r',encoding='utf-8')

    python2中的file与open

    #首先在python3中操作文件只有一种选择,那就是open()
    
    #而在python2中则有两种方式:file()与open()
    两者都能够打开文件,对文件进行操作,也具有相似的用法和参数,但是,这两种文件打开方式有本质的区别,file为文件类,用file()来打开文件,相当于这是在构造文件类,而用open()打开文件,是用python的内建函数来操作,我们一般使用open()打开文件进行操作,而用file当做一个类型,比如type(f) is file

    二 打开文件的模式

    文件句柄 = open('文件路径', '模式')
    
    
    #1. 打开文件的模式有(默认为文本模式):
    r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
    w,只写模式【不可读;不存在则创建;存在则清空内容】
    a, 之追加写模式【不可读;不存在则创建;存在则只追加内容】
    
    #2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
    rb 
    wb
    ab
    注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
    
    #3. 了解部分
    "+" 表示可以同时读写某个文件
    r+, 读写【可读,可写】
    w+,写读【可读,可写】
    a+, 写读【可读,可写】
    
    
    x, 只写模式【不可读;不存在则创建,存在则报错】
    x+ ,写读【可读,可写】
    xb

    三 操作文件方法

    #掌握
    f.read() #读取所有内容,光标移动到文件末尾
    f.readline() #读取一行内容,光标移动到第二行首部
    f.readlines() #读取每一行内容,存放于列表中
    
    f.write('1111
    222
    ') #针对文本模式的写,需要自己写换行符
    f.write('1111
    222
    '.encode('utf-8')) #针对b模式的写,需要自己写换行符
    f.writelines(['333
    ','444
    ']) #文件模式
    f.writelines([bytes('333
    ',encoding='utf-8'),'444
    '.encode('utf-8')]) #b模式
    
    #了解
    f.readable() #文件是否可读
    f.writable() #文件是否可读
    f.closed #文件是否关闭
    f.encoding #如果文件打开模式为b,则没有该属性
    f.flush() #立刻将文件内容从内存刷到硬盘
    f.name

    四 文件内光标移动

    一: read(3):
    
      1. 文件打开方式为文本模式时,代表读取3个字符
    
      2. 文件打开方式为b模式时,代表读取3个字节
    
    二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
    
    注意:
    
      1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
    
      2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
        
      刚打开文件就调用它会清空文件。
    file.seek()方法标准格式是:seek(offset,whence=0)
    
    offset:开始的偏移量,也就是代表需要移动偏移的字节数
    
    whence:给offset参数一个定义,表示要从哪个位置开始偏移;
    0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。默认为0
    
    
    一个相关的例子: 用yield生成器模拟Linux中命令:tail -f file | grep python 用于查找监控日志文件中出现有python字样的行
    
    
    # 注意程序只检测新增的日志信息!
    #当程序运行时,若warn.log文件中末尾有新增一行,且该一行包含python,该行就会被打印出来
    #若打开warn.log时,末尾已经有了一行包含python,该行不会被打印,因为上面是f.seek(0,2)移动到了文件EOF处
    #故,上面程序实现了tail -f warn.log | grep 'python'的功能,动态实时检测warn.log中是否新增现了
    #新的行,且该行包含python
    
    def tail(f):
        # 移动到文件的EOF最后
        f.seek(0.2)
        while 1:
            # 读取文件中新的文本行
            line = f.readline()
            if not line:continue
            # yield 出每一行的数据
            yield line
    
    def grep(lines,search_text):
        for line in lines:
            if search_text in line:
                yield line
    
    if __name__ == '__main__':
        flog = tail(open('log.log'))
        py_lines = grep(flog,'python')
        for line in py_lines:
            print(line)

    五 文件的修改

    文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:

    方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

    import os
    
    with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
        data=read_f.read() #全部读入内存,如果文件很大,会很卡
        data=data.replace('alex','SB') #在内存中完成修改
    
        write_f.write(data) #一次性写入新文件
    
    os.remove('a.txt')
    os.rename('.a.txt.swap','a.txt')

    方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件

    import os
    
    with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
        for line in read_f:
            line=line.replace('alex','SB')
            write_f.write(line)
    
    os.remove('a.txt')
    os.rename('.a.txt.swap','a.txt')

    六 自己的一些收集

    linux上处理windows上的文件时最好用 rb wb,还有进行文件传输的时候也要用b(二进制),避免 编码方式的不同导致错误,而且文件中不止文本有图片等的情况会出错.b模式跨平台,因为所有系统存储数据都是二进制.

    1.python 2.x中:
    默认都是读取文本文件,并且是ASCII编码的文本文件。要读取二进制文件,比如图片、视频等等,
    用'rb'模式打开文件即可:
    
    >>> f = open('/Users/michael/test.jpg', 'rb')
    >>> f.read()
    'xffxd8xffxe1x00x18Exifx00x00...' # 十六进制表示的字节
    
    字符编码:读取非ASCII编码的文本文件,就必须以二进制模式打开,再解码。比如GBK编码的文件:
    >>> f = open('/Users/michael/gbk.txt', 'rb')
    >>> u = f.read().decode('gbk') #将二进制解码,存文件encode,读取文件decode
    >>> u
    u'u6d4bu8bd5'
    >>> print u
    测试

    6.1文件读写注意:文件写入的是字符串,不能这样

    a = [1,2,3]
    f.write(a)
    不能f.write(5)

    f = open(‘1.txt’,’w’,’buffersize’),其实跟file是一样的,是file的别名。 文件打开的过程中不能更改模式,除非r+或者w+模式。

     with open('1.txt','w','buffersize') as f:
         f.write('aaa')  #w模式不会自动换行,需要加上 
    ,a 模式会自动加上
    
         f.writelines(['12
    ''34
    '])
         f.close() #关闭文件,with模式下不用,会自动关闭。
    
         f.seek(-1,2), 从文件末尾为原点计算,读取倒数第一个字符
         f.read()
         f.readline()
         f.readlines() 读取整个文件为列表,将文件全部读取到内存
    
         f.xreadlines() 一行一行读取到内存中,处理大文件必须要用它,不要用readlines。
         f.write()
         f.writeline()
         f.truncate()  #截取文件,默认截取到当前位置。刚打开文件就调用它会清空文件。
         f.flush()  #将文件内存中的内容写到磁盘
    
     注意:linux上处理windows上的文件时最好用 rb   wb,还有进行文件传输的时候也要用b(二进制),避免编码方式的不同导致错误。
    
    
     f = file('1.txt','w')    #帮助  help(file),跟open是一样的
    
    操作方法同上
    
    
     f = file('test.txt','r')
     遍历文件
         for line in f.xreadlines(): #大文件必须用xreadlines()一行一行读
             print line,   #加上,  不打印换行符

    6.2文件内容更改

    fileinput模块提供处理一个或多个文本文件的功能,可以通过使用for循环来读取一个或多个文本文件的所有行。
    
    【默认格式】
    
        fileinput.input (files='filename', inplace=False, backup='', bufsize=0, mode='r', openhook=None)
    
        files:         #文件的路径列表,默认是stdin方式,多文件['1.txt','2.txt',...]
        inplace:       #是否将标准输出的结果写回文件,默认不取代
        backup:        #备份文件的扩展名,只指定扩展名,如.bak。如果该文件的备份文件已存在,则会自动覆盖。
        bufsize:       #缓冲区大小,默认为0,如果文件很大,可以修改此参数,一般默认即可
        mode:      #读写模式,默认为只读
        openhook:    #该钩子用于控制打开的所有文件,比如说编码方式等;
    
    【常用函数】
    
    
        1 fileinput.input()       #返回能够用于for循环遍历的对象
        2 fileinput.filename()    #返回当前文件的名称
        3 fileinput.lineno()      #返回当前已经读取的行的数量(或者序号)
        4 fileinput.filelineno()  #返回当前读取的行的行号
        5 fileinput.isfirstline() #检查当前行是否是文件的第一行
        6 fileinput.isstdin()     #判断最后一行是否从stdin中读取
        7 fileinput.close()       #关闭队列
    
    实例:替换Rain为Jerry
    
        for line in fileinput.input('user.txt',backup='.bak',inplace=1):
            line = line.replace('Rain','Jerry')
            print line,

    实例:向文件中指定位置插入内容

    def file_insert(fname, str):
        r = ur'}'
        f = open(fname)
        old = f.read()
        num = int(re.search(r, old).start()) #正则找到要插入到的位置。
    
        f_input = fileinput.input(fname, inplace=1)
        #for line in fileinput.input(fname, inplace=1):
        for line in f_input:
            if r in line:
                print line.rstrip() #让stdout被重定向到输入文件里
                print "
    "+str+"
    " #让stdout被重定向到输入文件里,str是要插入的内容
                f.seek(num+2) #移动到插入位置末尾。
                print f.read() #让stdout被重定向到输入文件里,将剩余的内容打印
                break
            else:
                print line.rstrip()
        f.close()
        f_input.close()
        #print "OK! The %s configure has been sucessfull added!" % fname
        print "Ok! 配置文件%s已经添加成功!" % fname
    
    注意: fileinput.input的inplace必须要设为1,以便让stdout被重定向到输入文件里。

    6.3大文件迭代方法:

    1.while + readline
    f = open('text.txt',r)
    while true:
        line = f.readline()  一行一行读取,每读取一行文件指针移动到下一行
        if line:
            pass
         else:
            break
    
    2.xrandlines()
    
    3.文本文件自带的迭代:
    f = open('text.txt',r)
    for i in f:
        pass
    
    4.用yield生成器。

    6.4核心笔记:保留分行符

    当使用输入方法如read()或者readlines()从文件度取行时,python不会删除结束符。文件写操作一样不会写入 结束符号(n).

     

    行分隔符和其它文件系统的差异:不同操作系统所支持的行分隔符,路径分隔符,都不同。为了有助于跨平台开发, os模块的以下属性,在不同平台会自动设置成相应的值。

    >>> import os
    >>> os.linesep
    '
    '
    >>> os.pathsep
    ':'
    >>> os.sep
    '/'
    >>> os.curdir
    '.'
    >>> os.pardir
    '..'
    >>>

    6.5标准文件: sys.stdin sys.stdout sys.stderr

    标准输入:一般是键盘。stdin对象为解释器提供输入字符流,一般使用raw_input()和input()函数。 name = sys.stdin.readline() 相当于 raw_input()

    标准输出:一般是屏幕。stdout对象接收到print语句产生的输出。 sys.stdout.write()方法其实就是上面所讲的标准输出,print语句就是调用了这个方法

    错误输出:一般是错误信息。stderr对象接收出错的信息。

    实例:从控制台重定向到文件。

    记住,如果你还想在控制台打印一些东西的话,最好先将原始的控制台对象引用保存下来, 向文件中打印之后再恢复 sys.stdout:

    _console__ = sys.stdout #保存原始控制台
    
    import sys
    
    f_handler=open('out.log', 'w')
    sys.stdout=f_handler     #标准输出重定向到文件
    print 'hello'
    print 'hello'
    print 'hello'
    f_handler.close()
    
    sys.stdout= __console__  #恢复控制台
    print 'console'
  • 相关阅读:
    Spring优势
    Spring中的设计模式
    Spring MVC体系结构
    《Spring3.0就这么简单》第1章快速入门
    InvocationHandler
    JdkDynamicAopProxy源码
    Proxy代理(AOP实现原理)
    Spring AOP 实现原理
    BeanFactory和ApplicationContext的作用和区别
    背景图片相关设置
  • 原文地址:https://www.cnblogs.com/yitianyouyitian/p/8622785.html
Copyright © 2011-2022 走看看