zoukankan      html  css  js  c++  java
  • python文件操作(二)

    一、二进制处理文件

           通过前面的说明,我们知道‘b’模式是通过字节的形式来读写文件,但是要理解一点的是,这种模式只是在内部处理的时候是字节,但是我们打开文件看到的还是字符串的形式,而不是一堆字节。还有一点需要了解的是,在linux系统里面,‘b’模式是没有作用的,因为linux理念的是一切皆文件,他本来所有的文件都是通过字节操作的,所以如果要跨平台处理文件,需要用到‘b’模式。

    1.‘rb’模式

           下面就来演示‘b’模式读取一个py文件,py文件的内容如下: 

    hello
    11111
    22222
    33333

           根据前面的内容,我们一般这么写:

    f=open('test11.py','rb',encoding='utf-8') #b的方式不能指定编码
    data=f.read()
    print(data)
    f.close()

            但是运行后会发现报错,ValueError: binary mode doesn't take an encoding argument,b的方式不能指定编码,为什么不能指定?因为你文件存在硬盘的方式就是一堆二进制,之所以你能看到字符串,是因为你是用应用程序打开的文件,应用程序有不同的编码方式,所以如果你是‘r’模式去读,要区分编码,如果是‘rb’模式去读,读的是原生的二进制,就不用应用程序编码了,所以会报错。

          所以正确的写法是这样的:

    f=open('test11.py','rb') #b的方式不能指定编码
    data=f.read()
    print(data)
    f.close()

          拿到的结果是:

    b'hello
    11111
    22222
    33333'

          前面这个b,就说面这一个字节内容,如果在源文件加一列中文,结果会是:

    b'hello
    11111
    22222
    33333
    xe4xbdxa0xe5xa5xbd'

          如果你想看到你原本写的字符串,就要对结果进行解码(对应你写入字符串时的编码,我这里写入时为‘utf-8’编码),也就是decode:

    f=open('test11.py','rb') #b的方式不能指定编码
    data=f.read()
    #'字符串'---------encode---------》bytes
    #bytes---------decode---------》'字符串'
    # print(data)
    print(data.decode('utf-8'))
    f.close()

          这时看到的结果就是:

    hello
    11111
    22222
    33333
    你好

          这里有一个小的补充:windows里面的回车 ,linux和unix的回车则直接是 ,所以跨系统传文件打开后看到的会有一些偏差,原因可能就是这个。

    2.‘wb’模式

          读文件我们会了,写文件也是一样的,我们写入也要写入bytes形式的,字符串转换成字节可以通过bytes()函数实现。

    f=open('test22.py','wb') #b的方式不能指定编码
    f.write(bytes('1111
    ',encoding='utf-8'))
    f.close()

           运行完之后我们拿到一个新文件,里面的内容就是1111,这里面写中文也是可以的。字符串转字节是一种编码过程,那我们是不是可以用encode方法呢?

    f=open('test22.py','wb') #b的方式不能指定编码
    # f.write(bytes('你好
    ',encoding='utf-8'))
    f.write('你好'.encode('utf-8'))
    f.close()

         运行完之后,结果同样OK。‘ab’模式用法就不多说了,和前面的a类似。现在有一个疑问,为什么我们要用b模式来处理文件?那我用r/w/a也可以完成上面的操作。原因有两点:

    1.文件不仅仅只有文本这一种形式,还有图片视频等,这些非文本形式你用r/w/a处理不了;

    2.就是之前说过的,你需要跨平台处理文件的时候,不管你什么平台,你最后处理的都是一堆二进制;

    二、文件操作的其他方法

         操作文件的方法除了之前说read、readlines、readline、write等,还有其他方法可以了解一下:

    1.f.encoding (如果文件打开模式为b,则没有该属性)

    f=open('a.txt','r+',encoding='gb2312')
    print(f.encoding)
    f.close()
    
    >>>gb2312

           这里拿到的文件打开的编码,切记,和源文件以什么方式存放到硬盘的方式无关。无法解决你因为不知道源文件编码时,打开文件乱码的问题。不过这种情况很少见,大部分情况你都是知道源文件编码的,如果真的遇到这种情况,就可以用一种encoding='latin-1'的编码去打开,这种编码兼容了大部分的编码方式。

    2.f.flush() (立刻将文件内容从内存刷到硬盘)

           当你通过open打开一个文件的时候,你写的东西其实都是内存里面,并没有保存在硬盘中,你不保存,这些数据就一直在内存中,假如关闭或断电了就没了。可是你会发现这种情况在pycharm里面,你没有保存,文件内容断电之后也还存在,这是因为这些应用程序每隔几秒就自动帮你保存一次,这种保存的方法就是flush(),你可以在cmd里面实验这种情况。

    3.f.tell() (返回文件光标所在的位置)

            现在有一个文件,就写了一行hello,看看tell返回什么   

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

    >>>0
    >>>5

            返回的就是当前光标的位置,注意当有多行时,会加上回车的两个字节。

    4.python做的好事!

           上面我们说过,Windows的回车是 ,下面看一下:

    f=open('b.txt','r',encoding='utf-8')
    print(f.readlines())
    f.close()
    
    >>>['hello
    ', '11111']

           怎么我打印出来只有 呢?这就是python帮你处理过的结果,想要拿到真正的结果,还要加上一个newline=''

    f=open('b.txt','r+',encoding='utf-8',newline='') #读取文件中真正的换行符号
    print(f.readlines())
    f.close()
    
    >>>['hello
    ', '11111']

            这样拿到的才是真实的结果,不过这没什么用,了解一下就行。

    5.f.seek()

           在讲这个之前,要先了解一下光标移动的两个点:

           一: read(3):

      1. 文件打开方式为文本模式时,代表读取3个字符

      2. 文件打开方式为b模式时,代表读取3个字节

           二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate

    f=open('b.txt','r+',encoding='utf-8')
    f.seek(1)
    print(f.tell())
    f.seek(3)
    print(f.tell())
    
    >>>1
    >>>3

          这就很容易理解了,但是如果你是中文开头的,一个中文是3个字节,你seek(1)的话就要报错了。还有一点就是,这里的seek都是以0为基准进行移动的。这种是默认情况,seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的。建议试一下read和seek的区别。

    f=open('b.txt','rb')
    print(f.tell())
    f.seek(10,1)
    print(f.tell())
    f.seek(3,1)
    print(f.tell())
    
    >>>0
    >>>10
    >>>13

           从上可知,seek模式改为1,就变为相对位置了。再改为2试试:

    f=open('b.txt','rb')
    print(f.tell())
    f.seek(-5,2)
    print(f.read())
    print(f.tell())
    f.seek(3,1)
    print(f.tell())
    
    >>>0
    >>>b'11111'
    >>>12
    >>>15

           模式2就是倒着seek,倒着移动的话,里面的参数也要写成负数,注意了。那么这个seek有什么用呢,就要在实际场景中去思考了。

    6. f.truncate([size]) 把文件裁成规定的大小

        如果size比文件大小还大, 这个会根据系统的不同可能不改变文件,可能补充0进去,或者补充一些随机的内容。truncate(10)就是从开头截取到第10个字节。所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下进行。

        其他方法很少用到,了解一下就行了。

             

  • 相关阅读:
    p3c安装使用 编码规范扫描 阿里巴巴出品,挺好用的
    Ideal test 不执行main方法了
    Maven 3-Maven依赖版本冲突的分析及解决小结
    (String)强制转换、toString()和String.valueOf()的区别
    Linux tail 命令详解
    iconv的安装和使用
    daemon函数的原理及使用详解
    SQL Sever 2012 如何建立数据库连接
    Navicat Premium 将sqlserver 数据库 导入mysql 中
    MySQL也有潜规则 – Select 语句不加 Order By 如何排序?
  • 原文地址:https://www.cnblogs.com/pengfy/p/10820557.html
Copyright © 2011-2022 走看看