• day09-字符编码补充以及文件处理


    上节课复习

    字符编码

    英文字符----------------------->内存:ASCII格式的二进制------------------>硬盘:ASCII格式的二进制
    中文字符,英文字符--------------->内存:gbk格式的二进制------------------>硬盘:gbk格式的二进制
    日文字符,英文字符--------------->内存:ASCII格式的二进制--------------->硬盘:shift-jis格式的二进制
    				
                 编码				  编码
    英文字符--------------->内存:ASCII格式的二进制------------------>硬盘:ASCII格式的二进制
    英文字符--------------->内存:ASCII格式的二进制------------------>硬盘:ASCII格式的二进制
    英文字符--------------->内存:ASCII格式的二进制------------------>硬盘:ASCII格式的二进制
    

    如何保证不乱码:

    存乱了:
    	1.统一用utf-8编码存入硬盘
    读乱了:
    	2.将读的编码改成与存的编码一致
    

    今日内容

    1.字符编码

    前言:

    运行python程序的三个步骤:python a.py
    
    1. 先启动python
    
    2. 解释器会将文本文件a.py内容由硬盘读入内存
    
    3. 解释器会解释执行刚刚读入内存的内容,识别python语法
    

    在python程序执行的前俩步涉及到字符编码时

    Python2中默认的编码格式是 ASCII 格式,在没修改编码格式时无法正确打印汉字,所以在读取中文时会报错。

    解决方法为只要在文件开头加入 # -*- coding: UTF-8 -*- 或者 # coding=utf-8 就行了

    注意:****# coding=utf-8 = 号两边不要空格。

    Python3.X 源码文件默认使用utf-8编码,所以可以正常解析字符,无需指定 UTF-8 编码。

    注意:如果你使用编辑器,同时需要设置 py 文件存储的格式为 UTF-8,否则会出现类似以下错误信息:

    SyntaxError: (unicode error) ‘utf-8’ codec can’t decode byte 0xc4 in position 0:
    invalid continuation byte
    

    Pycharm 设置默认字符编码步骤:

    • 进入 file > Settings,在输入框搜索 encoding
    • 找到 Editor > File encodings,将 IDE EncodingProject Encoding 设置为utf-8。

    print()功能对字符串类型的特殊照顾之申请内存空间

    print()会对字符串类型的二进制做特殊的处理"
    在python3中将字符对应的Unicode二进制存到内存空间中,取的时候,会将这个unicode二进制数解码成字符,所以在python3中看不到unicode的二进制数,会直接返回人类的字符
    而在python2中,它又会将unicode二进制转成指定的其他编码的格式的二进制放到内存空间中,它在反解的时候会根据不同的调用者(cmd,pycharm)去将Unicode二进制
    转成字符,因为调用者的解码的那个字符编码表是设置死的,这时候,它会存在俩个字符编码表不一致的情况,就会发生乱码
    解决方案: 在python2 中定义一个变量 字符前面加个 u 表示将它存到内存空间强制存为Unicode的二进制,又可以

    通过Unicode的二进制和字符的对应关系解码直接变为字符打印出来
    但是将字符类型的存到一个列表中,你又会发现,他取出来的还是unicode的二进制,并不会输出字符.

    总结:

    python3在第三步时会将unicode二进制存到内存空间,然后直接反解码成字符

    python2会将Unicode二进制转换成对应的编码的二进制,解码

    强调:在python3里,只会将Unicode格式的数字转成字符

    编码和解码的过程

    ​ 编码 编码

    字符-------------------->unicode------------->其他编码

    ​ 解码 解码

    字符<--------------------unicode<-------------其他编码

    x = "上"  # 内存中存的是'上'这个字符的unicode的二进制数
    print(x)  # 上  本解释器为python3 可以直接将字符类型
    print([x,])  # ===> ['上'] # 不管存到了其他数据类型中还是字符类型,都会将字符串打印到终端
    
    res = x.encode("gbk")  # 将unicode二进制x通过gbk编码成gbk二进制
    print(type(res))  # <class 'bytes'>  # 类型是bytes
    
    # 强调:在python3里,只会将unicode格式的数字转成字符,其余编码格式的数字均不会转换
    print(res)  # b'xc9xcf'
    print(res.decode("gbk"))  # 上
    

    2.文件处理

    • 控制文件读写操作的模式"

      • r:只读
      • w:只写
      • a:只追加
    • 控制文件读写内容的模式:

      • t:控制读写的内容都是字符串类型
        • 只适用于文本文件
        • 必须要只读encoding参数
      • b:控制读写的内存都是bytes类型
        • 一定不要指定encoding参数

      b使用的情况居多,因为文件存到硬盘都是存的二进制.

    3.文件读写方法

    r:只读

    r:如果文件不存在则报错,文件存在则将文件指针跳转到整个文件的开头

    完整语法:f = open('file_path', mode='rt', encoding='')

    • file_path为读的文件的路径
    • mode=''为指定的模式
    • encoding=''为指定按照上面字符编码表解码到内存

    案例:打印出a.txt中的所有内容

    f = open('a.txt', mode='rt', encoding='utf-8')
    
    print(f.read())
    f.close()
    

    w:只写

    w:如果文件不存在则创建空文档,如果文件存在则清空,文件指针跳转到文件开头

    完整语法::f = open('file_path', mode='wt', encoding='')

    • file_path为写的文件的路径
    • mode=''为指定的模式
    • encoding=''为指定按照上面字符编码表编码到硬盘

    案例:往c.txt文件中写入一些内容

    f = open('c.txt', mode='wt', encoding='utf-8')
    f.write('你好啊1')
    f.write('你好啊2')  # 打开了文件不关闭的情况下,新写入的内容永远跟在老内容后面
    f.write('你好啊3')
    
    f.close()
    

    a:追加模式

    a: 如果文件不存则创建空文档,如果文件存在则清空,文件指针跳到文件末尾

    完整语法::f = open('file_path', mode='at', encoding='')

    • file_path为写的文件的路径
    • mode=''为指定的模式
    • encoding=''为指定按照上面字符编码表编码到硬盘

    案例:往c.txt文件中追加内容

    f = open(r'c.txt',mode='at',encoding='utf-8')
    f.write("你好啊1
    ")
    f.write("你好啊2
    ")  # 打开了文件不关闭的情况下,新写入的内容永远跟在老内容之后
    f.write("你好啊3
    ")
    f.close()
    

    读写模式

    r+t 在保持读的基本情况下还可以写
    w+t 在保持写的基本情况下还可以读
    a+t 在保持追加写的基本情况下还可以读

    例如:读写c.txt中的内容

    f = open(r'c.txt',mode='r+t',encoding='utf-8')
    print(f.readable())
    print(f.writable())
    print(f.read())
    
    f.write("h")
    f.close()
    

    b模式

    必须配合r,w,a 使用

    作用:不仅可以读写普通的文本文件还可以读写操作二进制的文件,原理是都是以二进制的类型进行操作

    b模式配合读写操作文件案例:

    将c.txt文件的bytes类型的二进制读取出来

    with open('c.txt',mode='rb') as f:
        res = f.read()
        # print(type(res))
        # print(res)  # 结果是bytes类型的二进制
        print(res.decode('utf-8'))  # 可以解码成原本的字符
    

    将1.mp4这个视频文件的内容读取出来

    with open('1.mp4',mode='rb') as f:
        print(f.read())
        for line in f:
            print(line)
    

    copy一份1.mp4的视频文件

    with open('1.mp4',mode='rb') as src_f,open(r'D:111111.mp4',mode='wb') as dst_f:
        for line in src_f:
            dst_f.write(line)
    

    怎么将字符以bytes类型的二进制写入到文件中

    with open('d.txt',mode='wb') as f:
        msg = "你好"
        f.write(msg.encode('utf-8'))
    

    file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:

    序号 方法及描述
    1 file.close()关闭文件。关闭后文件不能再进行读写操作。
    2 file.flush()刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。
    3 file.fileno()返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。
    4 file.isatty()如果文件连接到一个终端设备返回 True,否则返回 False。
    5 file.next()返回文件下一行。
    6 file.read(size)从文件读取指定的字节数,如果未给定或为负则读取所有。
    7 file.readline(size)读取整行,包括 " " 字符。
    8 file.readlines(sizeint)读取所有行并返回列表,若给定sizeint>0,则是设置一次读多少字节,这是为了减轻读取压力。
    9 file.seek(offset, whence)设置文件当前位置
    10 file.tell()返回文件当前位置。
    11 file.truncate(size)截取文件,截取的字节通过size指定,默认为当前文件位置。
    12 file.write(str)将字符串写入文件,返回的是写入的字符长度。
    13 file.writelines(sequence)向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。

    比较常用的方法

    read()方法

    功能:用于从文件读取指定的字节数,如果未给定或为负则读取所有。

    语法: fileObject.read([size])

    • size -- 从文件中读取的字节数,默认为 -1,表示读取整个文件。

    返回值:返回从字符串中读取的字节。

    readline() 方法

    功能:用于从文件读取整行,包括 " " 字符。如果指定了一个非负数的参数,则返回指定大小的字节数,包括 " " 字符。

    语法:fileObject.readline(size)

    • size -- 从文件中读取的字节数

    readlines()方法

    功能:用于读取所有行(直到结束符 EOF)并返回列表,该列表可以由 Python 的 for... in ... 结构进行处理。

    如果碰到结束符 EOF 则返回空字符串。

    语法:fileObject.readlines( )

    返回值: 返回列表,包含所有的行。

    write() 方法

    功能:用于向文件中写入指定字符串。

    注意:

    在文件关闭前或缓冲区刷新前,字符串内容存储在缓冲区中,这时你在文件中是看不到写入的内容的。
    
    如果文件打开模式带 b,那写入文件内容时,str (参数)要用 encode 方法转为 bytes 形式,否则报错:TypeError: a bytes-like object is required, not 'str'。
    

    语法:fileObject.write( [ str ])

    • str为当wt就是字符串/当是wb模式则是字节

    返回值: 返回的是写入的字符长度。

    writelines() 方法

    功能:用于向文件中写入一序列的字符串。

    • 这一序列字符串可以是由迭代对象产生的,如一个字符串列表。换行需要制定换行符 。

    语法:fileObject.writelines( [ str ])

    • str为当wt就是字符串列表/当是wb模式则是字节

    没有返回值

    seek() 方法

    功能:用于移动文件读取指针到指定位置。

    语法:fileObject.seek(offset[, whence])

    • offset-- 开始的偏移量,也就是代表需要移动偏移的字节数
    • whence可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
    • 注意:只有0模式可以在t下使用,1和2只能在b模式下使用

    返回值: 如果操作成功,则返回新的文件位置,如果操作失败,则返回 -1。

    实例1:

    with open('a.txt',mode='rt',encoding='utf-8') as f:
        f.seek(3,0)
        f.seek(5,0)
        print(f.tell())  # 5
    
    with open('a.txt',mode='rb') as f:
        f.seek(3,1)
        f.seek(5,1)
        print(f.tell())  # 8
        res=f.read()
        print(res.decode('utf-8'))
    
    with open('a.txt',mode='rb') as f:
        f.seek(-3,2)
        print(f.tell()) 
        f.seek(0,2)
    

    练习:动态监测文件最后一行加入的内容

    import time
    with open('access.log',mode='at',encoding='utf-8') as f7:
        f7.write(f'{time.strftime("%Y-%m-%d %H:%M:%S")},jkey给liu转了1个亿
    ')
        # 执行一遍就在末尾追加一行记录
    
    # 监视着文件的动态,来一行打印一行
    with open('access.log', mode='rb') as f8:
        f.seek(0, 2)  # 将指针一直放在末尾
        while True:
            line4 = f8.readline()
            if len(line4) == 0:
                time.sleep(0.1)
            else:
                print(line4.decode('utf-8'), end='')
                pass
    

    4.文件修改的俩种方式

    修改文件的方式1:

    在内存中进行修改,只用到一个文件

    1. 先将文件内容全部读入内存

    2. 在内存种完成修改

    3. 将修改后的内容覆盖回原文件

      ps : 耗内存不消耗硬盘

    with open('access.log') as f9:
        data = f9.read()
    
    with open('access.log',mode='wt', encoding='utf-8') as f10:
        f10.write(data.replace('egon','EGON'))
    

    修改文件的方式2:

    一行一行的copy到另外一个文件,最后删除原文件,重命名新文件为原文件名称

    1. 以读的方式打开原文件,然后以写的方式打开一个临时文件

    2. 读原文件的一行内容到内存,然后在内存中修改完毕后在写入临时文件,循环往复直到全部改完

    3. 删除原文件,将临时文件重命名为原文件名

      ps : 耗硬盘不消耗内存

    import os
    
    with open('name.txt', 'rt', encoding='utf-8') as f1, 
            open('name1.txt', 'wt', encoding='utf-8') as f2:
        for i in f1:
            i = i.replace('alex', 'sb')
            f2.write(i)
    
    os.remove('name.txt')
    os.rename('name1.txt', 'name.txt')
    
  • 相关阅读:
    strcmp()比较函数和strcasecmp()和strnatcmp()
    substr()函数
    改变字符串中的字母大小写
    explode()与相反函数 implode() 和join()
    PHP nl2br() 函数
    PHP trim() 函数
    PHP的count(数组)和strlen(字符串)的内部实现
    变量处理函数库
    php中定义数组的方法
    80端口的烦恼:[3]清除NT Kernel占用80端口
  • 原文地址:https://www.cnblogs.com/jkeykey/p/14190859.html
Copyright © 2020-2023  润新知