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

    1 文件操作

      无论在那种语言中都会对文件进行操作处理,而文件相关的处理无非就是打开文件,读取或者写入内容,最后再是关闭文件。Python中文件常用的IO操作有以下几个:

    Function Operation
    open 打开
    read 读取
    write 写入
    close 关闭
    readline 行读取
    readlines 多行读取
    seek 文件指针操作
    tell 指针位置

    2 打开操作

      文件的打开操作是对文件进行操作的第一步,Python中提供open函数,open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None),open 函数是打开一个文件,返回以文件对象(流对象)和文件描述符。打开文件失败,则返回异常。

    2.1 open函数基本使用

      创建一个文件test,然后打开它,用完关闭。

    1 f = open("test")    # file对象
    2 # windows <_io.TextIOWrapper name='test' mode='r' encoding='cp936'>
    3 # linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
    4 print(f.read())    # 读取文件
    5 f.close()    # 关闭文件
    View Code

      文件操作找那个,最常用的操作就是读和写。文件访问的模式有两种:文本模式和二进制模式。不同模式下,操作函数不尽相同,表现的结果也不一样。

    2.2 open函数的参数

    2.2.1 file

      open函数中的file文件是指定要打开或者要创建的文件名,如果不指定路径,默认是当前路径。

    2.2.3 mode模式

      open函数中提供mode参数,可以控制是以什么方式打开文件的,不同的模式适用不同场景下对文件的操作。以下是打开文件的模式以及其对应的作用:

    Description Meaning
    r 缺省的,表示只读打开
    w 只写打开
    x 创建并写入一个新文件
    a 写入打开,如果文件存在,则追加
    b 二进制模式
    t 缺省的,文本模式
    + 读写打开一个文件。给原来只读、只写方式打开提供缺失的读或者写能力

      在2.1的例子中,打开test文件时没有指定mode参数,那么就是默认以文本打开模式并且是以只读模式打开test文件。

    • r模式

      open默认是只读模式r打开已经存在的文件,如果文件不存在,抛出FileNotFoundErro异常。只读打开文件,如果使用write方法,会抛出异常。

    • w模式

      如果mode后是w描述符,表示只写方式打开文件,如果读取则抛出异常。如果文件不存在,则直接创建文件,如果文件存在,则清空文件内容。

    • x模式

      x模式下如果文件不存在,创建文件,并以只写方式打开文件;文件存在时,抛出FileExistsError异常。

    • a模式

      a模式下,文件存在,只写模式打开,追加内容;文件不存在,则创建后,只写模式打开文件,追加内容。

    • 文本模式t

      字符流,将文件的字节按照某种字符编码理解,按照字符操作。open的默认mode是rt。

    • 二进制模式b

      字节流,将文本按照字节理解,与字符编码无关。二进制模式操作是,字节操作使用bytes类型。

    • +模式

      为r、w、a、x提供确实的读写功能。但是,获取文件对象依旧按照r、w、a、x。+不能单独使用,可以认为它是为前面的模式字符做增强功能的。

    2.2.4 buffering: 缓冲区

      Python在处理文件时,是在内存中对文件进行处理。当给文件中写入内容是,不是立即将内容写入磁盘中,而是先写入内存中,存入缓冲区中待缓冲区满了或者在关闭文件之前,将内存中的内容写入磁盘中。

      缓冲区是一个内存空间,一般来说是一个FIFO队列,到缓冲区满了或者达到阈值时数据才会flush到磁盘。flush函数是将缓冲区数据写入磁盘,close()关闭前会调用flush函数。io.DEFAULT_BUFFER_SIZE缺省缓冲区大小,单位是字节,默认是4096或者8192。

      open函数中的buffering参数,用-1表示使用缺省大小的buffer。如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值;如果是文本模式,如果是是终端设备,是行缓方式,如果不是则使用二进制模式的策略。

    • 0只在二进制模式使用,表示关buffer
    • 1只在文本模式使用,表示使用行缓冲。意思就是见到换行符就flush
    • 大于1用于指定buffer的大小

    1、二进制下的例子

     1 import io
     2 
     3 f = open('test4', 'w+b')
     4 print(io.DEFAULT_BUFFER_SIZE)
     5 f.write('baidu.com'.encode())
     6 # cat test4
     7 f.seek(0)
     8 # cat test4
     9 f.write('www.baidu.com'.encode())
    10 f.flush()
    11 f.close()
    12 
    13 f = open('test4', 'w+b', 4)
    14 f.write(b'dab')
    15 # cat test4
    16 f.write(b'ric')
    17 # cat test4
    18 f.close
    View Code

    2、文本模式下

     1 # buffering=1,使用行缓冲
     2 f = open('test4', 'w+', 1)
     3 f.write('dab')    # cat test4
     4 f.write('dabric'*4)    # cat test4
     5 f.write('
    ')    # cat test4
     6 f.write('Hello
    Python')    # cat test4
     7 f.close
     8 
     9 # buffering>1,使用指定大小的缓冲区
    10 f = open('test4', 'w+', 15)
    11 f.write('dab')    # cat test4
    12 f.write('ric')    # cat test4
    13 f.write('Hello
    ')    # cat test4
    14 f.write('
    Python')    # cat test4
    15 f.write('a' * (io.DEFAULT_BUFFER_SIZE - 20))    # 设置为大于1没什么用
    16 f.write('
    www.baidu.com/python')
    17 f.close
    View Code

      buffering=0,这时一种特殊的二进制模式,不需要内存的buffer,可以看做是一个FIFO的文件。

    1 f = open('test4', 'wb+', 0)
    2 f.write(b'd')    # cat test4
    3 f.write(b'a')    # cat test4
    4 f.write(b'b')    # cat test4
    5 f.write(b'dabric'*4)    # cat test4
    6 f.write(b'
    ')    # cat test4
    7 f.write(b'Hello
    Python')    # cat test4
    8 f.close
    View Code

      buffering为不同值下多代表的含义总结如下表:

    buffering Introduction
    buffering=-1 t和b都是io.DEFAULT_BUFFER_SIZE
    buffering=0

    b关闭缓冲区

    t不支持

    buffering=1

    b就1个字节

    t行缓冲,遇到换行读才flush

    buffering>1

    b模式表示行缓冲大小。缓冲区的值可以超过io.DEFAULT_BUFFER_SIZE,

    直到设定的值超出后才把缓冲区flush

    t模式,是io.DEFAULT_BUFFER_SIZE,flush完后把当前字符串也写入磁盘

      似乎看起来很玛法,一般来说,只需记得以下几点:

    • 文本模式,一般都使用默认缓冲区大小
    • 二进制模式,是一个个字节的操作,可以指定buffer的大小
    • 一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它
    • 一般编程中,明确知道需要写磁盘了,都会手动调用一次flush,而不是等到自定flush或者close的时候

     2.2.5 encoding: 编码,仅文本模式使用

      文件在磁盘中的存储是以字节形式存储的,如果要讲文件显示在屏幕上的话,就要对其进行解码,反过来写入时就要对其进行编码。Python中的open函数会在读取文件时做必要的解码,以文本模式写入文件时还会做必要的编码,所以在对文件调用读取或者是写入操作都是字符串对象。

      encoding参数指定编码的格式,None标识使用缺省编码,依赖操作系统。windows下缺省GBK,Linux下缺省UTF-8。在对文件的读取和写入操作时要保证编码格式的一致,如果使用默认的编码格式的话,在不同的操作系统中可能会产生乱码的现象,如下:

    1 >>> open('cafe.txt', 'w', encoding='utf_8').write('café')
    2 4 
    3 >>> open('cafe.txt').read()
    4 'café'
    View Code

      写入时文件指定UTF-8编码,但是读取文件时没有那么做。有可能在对文件进行读取时是在windows环境下,那么windows环境下使用的默认编码集为GBK,于是就会产生乱码现在。解决办法是在读取操作之前,打开文件制定编码格式为UTF-8即可。 

    2.2.6 其他参数

    • errors

      errors参数标识什么样的编码错误将被捕获。一般情况下,None和strict表示有编码错误将抛出ValueError异常;ingore标识忽略编码错误。

    • newline

      newline参数表示在文本模式中的换行的转换。可以为None、''空串、" "、" "、" "。

      读时,None表示" "、" "、" "都被转换为' ';''表示不会自动转换通用换行符;其它合法字符表示换行符就是制定字符,就会按照制定字符分行。

      写时,None表示' '都会被替换为系统缺省分隔符os,linesep;' '或''表示' '不替换;其它合法字符表示' '会被替换为指定的字符。

    1 f = open('o:/test', 'w')
    2 f.write('python
    www.python.org
    www.baidu.com
    python3')
    3 f.close()
    4 
    5 newlines = [None, '', '
    ', '
    ']
    6 for nl in newlines:
    7     f = open('o:/test', 'r+', newline=nl)    # q缺省替换所有换行符
    8     print(f.readlines())
    9     f.close
    View Code
    • closefd

      关闭文件描述符,True表示关闭它。False会在文件关闭后保持这个描述符。fileobj.fileno()查看。

    3 读取操作

    3.1 read函数

      read函数读取文件时,将整个文件中的内容读取到内存中,对于小文件的读取可以使用read,其不适用大文件的读取。read函数中的size参数表示读取的多少个字符或字节;负数或None表述读取到EOF。

     1 f = open('o:/test4', 'r+', 0)
     2 f.write("dabric")
     3 f.write('
    ')
     4 f.write('你好')
     5 f.seek(0)
     6 f.read(7)
     7 f.close
     8 
     9 # 二进制
    10 f = open('test4', 'rb+')
    11 f.read(7)
    12 f.read(1)
    13 f.close()
    View Code

    3.2 行读取

      readline函数表示一行行读取文件内容。size设置一个能读取行内几个字符或字节。

      readlines函数表述读取所有行的列表。指定hint则返回指定的行数。

    1 # 按行迭代
    2 f = open('test')    # 返回可迭代对象
    3 
    4 for line in f:
    5     print(line)
    6 
    7 f.close()
    View Code

    4 写入操作

      写入操作在前面的代码中多多少少都使用过,下面具体看下写入操作的函数。

      write(s),函数把字符串s写入到文件中并返回字符的个数;

      writelines(lines),将字符串列表写入文件。

    1 f = open('test', 'w+')
    2 
    3 lines = ['abc', '123
    ', 'dabric']    # 提供换行符
    4 f.writelines(lines)
    5 
    6 f.seek(0)
    7 print(f.read())
    8 f.close()
    View Code

    5 文件指针

       文件是通过文件指针来记录文件当前指向的字节位置,我们可以通过控制文件指针,来指向指定的字节位置。在模式为r的情况下,文件指针指向起始0位置,表示文件开头;在模式为a的情况下,文件指针指向EOF,表示文件末尾,所以a模式被称为追加模式。Python中提供tell函数来显示文件指针当前的位置。

    5.1 文件指针操作

      Python提供seek(offset[, whence])函数来系统文件指针位置。其中offset表示变异多少字节,whence表示从哪里开始。

      在文本模式下,whence的取值:

    • whence 0 缺省值,表示从文件头开始,offset只能为正整数
    • whence 1 表示从当前位置,offset只能接受0
    • whence 2 表示从EOF开始,offset只能接受0
     1 # 文本模式
     2 f = open('test4', 'r+')
     3 f.tell()    # 起始
     4 f.read()
     5 f.tell()    # EOF
     6 f.seek(0)    # 起始
     7 f.read()
     8 f.seek(2, 0)
     9 f.read()
    10 f.seek(2, 0)
    11 f.seek(2, 1)    # offset必须为0
    12 f.seek(2, 2)    # offset必须为0
    13 f.close()
    View Code

      文本模式支持从开头向后偏移的方式。whence为1表示从当前位置开始偏移,但是只支持偏移0,相当于原地不动,所以没有什么用;whence为2表示从EOF开始,只支持偏移0,相当于移动文件指针到EOF。seek函数时按照字节偏移的。

      在二进制模式下,whence的取值:

    • whence 0 缺省值,表示从文件头开始,offset只能为正整数
    • whence 1 表示从当前位置,offset可正可负
    • whence 2 表示从EOF开始,offset可正可负
     1 # 二进制模式
     2 f = open('test4', 'rb+')
     3 f.tell()    # 起始
     4 f.read()
     5 f.tell()    # EOF
     6 f.write(b'abc')
     7 f.seek(0)    # 起始
     8 f.seek(2, 1)    # 从当前指针开始,向后偏移2个字节
     9 f.read()
    10 f.seek(-2, 1)    # 从当前指针开始,向前偏移2个字节
    11 
    12 f.seek(2, 2)    # 从EOF开始,向后便宜2个字节
    13 f.seek(0)
    14 f.seek(-2, 2)    # 从EOF开始,向前偏移2个字节
    15 f.read()
    16 
    17 f.seek(-20, 2)    # OSError
    18 f.close()
    View Code

      二进制模式下支持任意起点的偏移,从头、从尾、从中间位置开始的偏移。向后seek可以超界,但是向前seek的时候,不能超界,否则抛出异常。

    6 上下文管理

      在每次打开使用文件结束后,都要使用close函数关闭文件对象,有时候在编程时难免会忘记使用close函数对打开的文件关闭,这样会导致该文件在其他地方不能使用的可能。Python提供一种上下文管理机制,使用它后在文件使用完后会自动关闭文件对象。

      使用with...as关键字,在with语句执行完的时候,会自动关闭文件对象。注意,上下文管理的语句块并不会开启新的作用域。

    1 with open('test') as f:
    2     f.write("abc")    # 文件只读,写入失败
    3 
    4 # 测试f是否关闭
    5 f.close    # f的作用域
    View Code

      另一种写法;

    1 f1 = open('test')
    2 with f1:
    3     f1.write('abc')    # 文件只读,写入失败
    4 
    5 # 测试f是否关闭
    6 f1.close    # f1的作用域
    View Code

      对于类似于文件对象的IO对象,一般来说都性需要在不使用的时候关闭、注销,以释放资源。IO被打开的时候,会获得一个文件描述符。计算资源是有限的,所以操作系统都会做限制。就是为了保护计算机的资源不要被完全耗尽,计算资源是共享的,不是独占的。一般情况下,除非特别明确的直到资源情况,否则不要提高资源的限制值来解决问题。

  • 相关阅读:
    第一章
    第一章 计算机系统漫游
    hihocoder #1014 : Trie树
    第一章
    来个小目标
    poj 1056 IMMEDIATE DECODABILITY
    poj 2001 Shortest Prefixes
    __name__ 指示模块应如何被加载
    Python 常用函数time.strftime()简介
    CentOS安装beEF做XSS平台
  • 原文地址:https://www.cnblogs.com/dabric/p/11746651.html
Copyright © 2011-2022 走看看