zoukankan      html  css  js  c++  java
  • open()函数详解

    要点概论:

    1. file 与 mode 参数

    2. buffering,encoding,errors,newlines参数

    3. stdin,stdout,stderr

    1. file 与 mode 参数

      file 可以是个字符串,指定读写文件的路径,可以指定相对路径或者绝对路径;

      mode 是使用字符串来指定文件打开的模式。

      先看一个基本款的文件打开模式表格:

    字符串 说明
    r 读取模式(默认)
    w 写入模式,会先清空文件内容
    x 只在文件不存在时才创建新文件并打开为写入模式,若文件已存在会引发 FileExistsError
    a 追加模式,若文件已存在,写入的内容会附加到文件尾端
    b 二进制模式
    t 文本模式(默认)
    + 更新模式(读取与写入)

     

      open() 的 mode 默认是 r ,在只指定 r , w ,x ,a 的情况下就相当于以文本模式打开,也就等同于 rt , wt , xt , at ,

      如果要以二进制模式打开,就要指定 rb , wb ,xb ,ab。

      如果想以更新模式打开,对于文本模式,可以使用 r+ , w+ , a+ ,对于二进制模式,可以使用 r+b , w+b , a+b。

      

      1)read(),write(),close()

        首先来看一个通用的 upper 程序,可使用命令行参数指定源与目标,将源文本文件的内容全部转成大写后写入目标文件:

    with open('小写字母表') as low,open('大写字母表','w') as upper:
        content = low.read()
        upper.write(content.upper())
    basicio upper

        read() 方法在未指定自变量的情况下会读取文件全部的内容。并返回 str 实例(二进制文件返回 bytes 实例),因此例子中可以使用 upper() 转换为大写。

        write() 方法可将指定的数据写入文件,write() 接受 str 实例并返回写入的字符数(二进制文件接受 bytes 实例并返回写入的字节数)。

        PS:read() 方法在指定整数自变量的情况下会读取指定的字符数(二进制为字节数)

        文件打开模式如果与后续进行的操作不符合,会引发 Unsupported Operation 异常,可以使用 readable() 方法测试是否可读取,writable() 方法测试是否可写入:

    f = open('测试表')
    f.write('是否能写入')       # io.UnsupportedOperation: not writable
    
    print(f.readable())          # True
    print(f.writable())          #False
    验证文件模式

      2)readline(),readlines(),writelines()

        文本模式和二进制模式通用。

        对于文本模式来说,默认读取到 'n',' 或 ' ' 时都可以被判定为一行,而readline() 或 readlines() 读到的每一行换行符都一律换为 ' ' 。

        对于二进制模式来说,行的判断标准默认时遇到 'b ' 这个 bytes 类型。

        文本模式在写入的情况下,任何 ' ' 都会被置换为 os.linesep 的值(Window 就是 ' ')。

        下面看一个'rb'模式打开文件,readlines() 的结果:

    f = open('测试表','rb')
    
    print(f.readlines())       #[b'111
    ', b'222
    ', b'333
    ', b'
    ', b'
    ', b'666']
    
    f.close()
    readlines() 读取

        可以看到,readlines()返回一个 列表(list),列表里每个元素时文件中被判定为一行的内容。

        

        下面是使用 readline() 搭配 while 循环的例子,因为 readline() 在都不到下一行时会返回空字符串,所以这样写:

    with open('测试表') as f:
        while True:
            line = f.readline()
            if not line:
                break
            print(line,end='')
    while 实现读取按行读取

        

        因为 open() 返回的文件对象都实现了 __iter__() 方法,可以返回一个迭代器,因此可以直接是哟个 for in 来进行迭代,每次迭代相当于执行 readline():

    with open('测试表') as f:
        for line in f:
            print(line,end='')
    for 循环实现按行读取

        PS:python的文件读取风格时:读取一个文件最好的方式就是不要去 read 。

      3)tell(),seek(),flush()

        在进行文件读取时, tell() 方法可以告知文件指针当前阿紫文件中的位置,单位时字节数,文件开头的位移量时 0 , seek() 方法可以指定跳到哪个位移量,如下例所示:

    with open('test','rb') as f:
    
        print(f.tell())    # 0
        
        print(f.read(1))   # b'1'
    
        print(f.read(1))   # b'2'
    
        print(f.tell())    # 2
    
        print(f.seek(1))   # 1
    
        print(f.read(1))   # b'2'
    test 模拟 12345 并存盘

        

        使用 seek() 来实现文件的随机存取,例如将第三个字节改为 b'0' :

    with open('test','r+b') as f:
        f.seek(2)
        print(f.write(b'0'))    # 1
    
        f.flush()
        f.seek(0)
    
        print(f.read())         # b'12045'
    seek() 实现文件随机存取

        主要不要写成 'w+b', 这样会清空文件内容,也不要写成 'a+b' ,这样会将写入的数据放到文件尾端。

        由于文件对象默认会缓冲处理,不一定会马上看到文件中写入了数据,这时可以执行 flush() 方法,将缓冲内容清空并写入文件。

      

      4)readto()

        在二进制模式中, read() 方法返回的 bytes 是不可变动的,如果想将读取到的字节数据收集到一个列表(list)中,基本上可以使用 list() ,例如:

    info = None
    with open('test2','rb') as f:
        info = f.read()
    
    print(list(info))        #[49, 50, 51, 52, 53]
    
    
    #test2 中文件内容为 12345
    test2

        除此之外,在二进制模式中的文件对象拥有一个 readinto() 方法接受 bytearray 实例,可以直接将读取到的数据传入,这样就可以不用中介的变量,例如:

    import os.path
    
    b_arr = bytearray(os.path.getsize('test2'))
    with open('test2','rb') as f:
        f.readinto(b_arr)
    
    print(b_arr[0])     # 49
    
    print(b_arr[1])     # 50
    
    print(b_arr)        # bytearray(b'12345')
    readinto()

        PS:两者通过索引获取的每个元素都是 int 类型,可以通过 bytes([value]) 将整数值转为 bytes ,例如 bytes([49]) 结果会是 b'1'

    2. buffering,encoding,errors,newlines 参数

      open() 函数一共有8个参数,除了常用的 file 与 mode 参数,这一部分介绍 buffering,encoding,errors 与 newlines 参数(closed,opener参数待补充)。

      

      1)buffering

        这个参数用来设置缓冲策略,默认的缓冲策略会试着自行决定缓冲区大小(通常为 4096 或 8192 字节),或者对互动文本文件( isatty() 为 True 时,例如 Windows的命令提示符)采取缓冲(line buffering)。

        buffering 设置为 0 表示关闭缓冲,设置为大于 0 的整数值表示指定缓冲区的字节大小。

        在前面的一个例子中如果采用 with open('test','r+b',buffering=0) as f ,在 f.write 更新文件之后不必使用 f.flush() ,马上就可以看到文件内容的变化:

    with open('test','r+b',buffering=0) as f:
        f.seek(2)
        print(f.write(b'0'))    # 1
    
        # f.flush()
        f.seek(0)
    
        print(f.read())         # b'12045'
    test

      2)encoding 与 errors

        encoding 是指定文件读取编码的参数。

        在 Windows 简体中文版中默认编码是 'cp936' 或 'gbk' (在 python 执行环境中,将 MS936 ,CP936,gbk 视为同一套编码)。

        

        errors 参数可指定发生编码错误时该如何处理。

        在不设置的情况下,发生编码错误时会引发 ValueError 的子类异常。

        例如 test3 文件中有 ‘方法已弃用’ 这几个汉字,并采用 utf-8 编码,如下方法读取,将会引发 UnicodeDecodeError 错误:

    with open('test3') as f:
        print(f.read()) 
    
    #UnicodeDecodeError: 'gbk' codec can't decode byte 0xa8 in position 14: incomplete multibyte sequence
    View Code

        如果设置 errors 为 ‘ignore’ ,那么会忽略错误,继续读取的操作,如下例所示:

    with open('test3',errors='ignore') as f:
        print(f.read())
    
    # 鏂规硶宸插純鐢
    View Code

         errors 的其他可设置选项请参考 open() 函数的说明

      3)newlines

        对于文本模式来说,默认读取到 ' ' ,' ' 或 ' 都可以被判定为一行,

        而 readline() 或 readlines() 读到的每一行一律保留来源的换行字符,如果设置为其他 ' ' ,' ' ,' ' ,那么读取后的换行字符就会时指定的字符。

        文本模式在写入的默认情况下,任何 ' ' 都会被置换为 os.linesep 的值。

        如果 newlines 设为 ‘’ 就保留原有的换行字符,如果指定为其他值,就以指定的字符进行置换。

    3. stdin ,stdout ,stderr

      目前获取用户的输入都是使用 input() 函数,若想显示指定的值,则使用 print() 函数,它们各自会使用预先连接的设备进行输入或输出。

      预先连接的输入,输出设备被称为标准输入(Standard input)与标准输出(Standard output),以个人计算机而言,通常对应到终端的输入与输出。

     

      在 sys 模块中有个 stdin 代表标准输入,stdout 代表标准输出,它们的操作就像 open() 函数打开的文本模式的文件对象。

      下面的例子模仿了 input() 函数的实现:

    import sys
    def console_input(prompt):
        sys.stdout.write(prompt)      # 使用标准输出
        sys.stdout.flush()            # 缓存清出数据到标准输出
        return sys.stdin.readline()   #使用标准输入读取一行
    name = console_input('请输入名称:')
    print('hello',name)
    stdin_demo

      在上面这个例子中, sys.stdout 的 write() 方法 “写出” 信息,为了能马上看到指定的信息显示,必须使用 flush() 方法清出数据(即将缓冲区中的数据清出到标准输出),

      接着可以使用 sys.stdin.readline() 读入一行输入的信息。

      对于标准输入或输出,若想要以二进制模式读取或写入,可以使用 sys.stdin.buffer 或 sys.stdout.buffer ,它们的操作或行为就像以 open() 函数打开的二进制模式的文件对象

      实际上可以改变标准输入或输出的来源,例如,将一个以 open() 函数打开的文件对象赋值给 sys.stdin 就可以利用 input() 来读取:

    import sys
    
    sys.stdin = open('stdin_demo.py',encoding='utf-8')
    
    print(input())      # import sys
    print(input())      # def console_input(prompt):
    print(input())      #     sys.stdout.write(prompt)      # 使用标准输出
    print(input())      #     sys.stdout.flush()            # 缓存清出数据到标准输出
    print(input())      #     return sys.stdin.readline()   #使用标准输入读取一行
    print(input())      # name = console_input('请输入名称:')
    print(input())      # print('hello',name)
    print(input())      # EOFError: EOF when reading a line
    读取stdin_demo中的内容

      类似地,将一个打开的文件对象赋值给 sys.stdout 就可以利用 print() 把数据写到文件中。

      不过内建的 print() 函数本身就有一个 file 参数可以满足这样的需求:

    with open('data.txt','w') as f:
        print('hello',file=f)
    View Code

      上面的程序执行过后,当前工作目录下就会创建一个 data.txt 文件(已有则覆盖),内容就是执行 print() 函数时输出的 'hello' 信息。

      

         

        

  • 相关阅读:
    有用的java工具
    AOP在大规模软件开发项目中的应用(图)
    java并发编程实践笔记
    深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题
    JVM相关问答
    软件架构设计的六大原则
    JVM 运行时数据区域
    JVM 类加载过程
    JVM 垃圾回收算法
    Memcached内存分配优化及使用问题
  • 原文地址:https://www.cnblogs.com/HZY258/p/8464512.html
Copyright © 2011-2022 走看看