zoukankan      html  css  js  c++  java
  • 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')
    
  • 相关阅读:
    使用JDBC连接MySql时出现:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration
    Mysql Lost connection to MySQL server at ‘reading initial communication packet', system error: 0
    mysql-基本命令
    C# 监听值的变化
    DataGrid样式
    C# 获取当前日期时间
    C# 中生成随机数
    递归和迭代
    PHP 时间转几分几秒
    PHP 根据整数ID,生成唯一字符串
  • 原文地址:https://www.cnblogs.com/jkeykey/p/14190859.html
Copyright © 2011-2022 走看看