zoukankan      html  css  js  c++  java
  • 字符编码、文件处理、指针移动

    目录:

      字符编码

      文件处理

      指针移动

    字符编码:

    储备知识点:
        1. 计算机系统分为三层:
            应用程序
            操作系统
            计算机硬件
    
        2. 运行python程序的三个步骤
            1. 先启动python解释器
            2. 再将python文件当作普通的文本文件读入内存
            3. 解释执行读入内存的代码,开始识别语法
    
    

    代码是在编辑器写的,不存在任何语法。

    边写边存到内存(Unicode编码),然后再通过解码显示到显示屏。从内存刷到硬盘时候,是从Unicode转换成你要保存的格式(GBK)。

    从硬盘读取出来的时候,先通过保存的格式(GBK)解码成Unicode到内存中,再用Unicode解码成原先写的字符。

     


    字符编码

    1. 什么是字符编码
    字符编码表: 人类的字符<------------>数字
            1Bytes=8bit
            1B=8b 1字节等于8个二进制位
    常用的编码表:
            ASCII码:只能识别英文字符,1英文字符=8bit=1Bytes
                    用8个二进制bit(比特位)位表示一个英文字符
    
            GBK:能识别汉字与英文,1汉字=16bit=2Bytes,1英文字符=8bit=1Bytes
    
            unicode:能够识别万国字符,1字符=2Bytes=16bit
                两大特点:
                    1. 能够兼容万国字符
                    2. 与各个国家的字符编码都有映射关系
            utf-8:是unicode的转换格式,在往硬盘存储时从unicode精简为utf-8,即从16bit转换为8bit,节省存储空间来提高运行速度。
              1个英文字符=1Bytes  1汉字=3Bytes
    
    
    字符串类型演变:
            
                python2有两种"字符串"相关类型:
                    种类一
                    #coding:gbk
                    x='' # '上'存成了GBK编码后的二进制
    
                    种类二:
                    x=u'' # '上'存成了unicode编码后的二进制
    
    
                python3有两种"字符串"相关类型
                    x='' # '上'存成了unicode编码后的二进制
    
                    res=x.encode('gbk') #gbk格式的二进制
            重点理论:
    1 编码与解码:
                    字符(输入)---编码-->unicode的二进制(存内存)-------编码----->GBK的二进制(存硬盘)
                    GBK的二进制(硬盘)-----解码-->unicode的二进制(内存)----解码->字符(显示器)
                2 解决乱码问题的核心法则:
    字符用什么编码格式编码的,就应该用什么编码格式进行解码

    3 python解释器默认的字符编码
    python2:ASCII(程序加载到内存中的时候都是unicode,开始识别语法时候会定义字符串变量,就会继续在内存中开辟空间,会使用ASCII编码)
    python3:Utf-8(Python3中,定义字符串变量时候,默认使用Unicode编码,和内存默认编码相同)

    通过文件头可以修改python解释器默认使用的字符编码
    在文件首行写:#coding:文件当初存的时候用的字符编码
    -------------------------------------------------------------------------------------------------

    针对python2解释器中定义字符串应该:
    x=u"上"
    对于python3解释即便是x="上"不加u前缀也是存成unicode
    -------------------------------------------------------------------------------------------------
    在python3中:
    x='上'   #上存成了unicode
    unicode--------encode(编码)----------->gbk(存储到硬盘时候转换成gbk)
       res=x.encode('gbk') #res是gbk格式的二进制,称之为bytes类型
    gbk(bytes类型)-------decode(解码)---------->unicode
    y=res.decode('gbk') #y就是unicode
    -------------------------------------------------------------------------------------------------
    关于字符编码的操作(结论
    1. 编写python文件,首行应该加文件头:#coding:文件存时用的编码(不用担心Python程序运行的前两个阶段,不会出现乱码)
    2. 用python2写程序,定义字符串应该加前缀u,如x=u''
    3. python3中的字符串都是unicode编码的,python3的字符串encode之后可以得到bytes类型

      2. 为何字符要编码
        人类与计算机打交道用的都是人类的字符,而计算机无法识别人类的字符,只能识别
        二进制,所以必须将人类的字符编码成计算机能识别的二进制数字.   3. 如何用字符编码

    文件处理:

    1 什么是文件
    文件是操作系统提供给用户/应用程序的一种虚拟单位,该虚拟单位直接映射的是硬盘空间

    2 为何要处理文件
    用户/应用程序直接操作文件(读/写)就被操作系统转换成具体的硬盘操作,从而实现
    用户/应用程序将内存中的数据永久保存到硬盘中

    3 如何用文件

    文件处理的三个步骤:
      f=open(r'c.txt',mode='r',encoding='utf-8') #打开文件,得到文件对象,f是文件对象(应用程序的内存资源)--》操作系统打开的文件(操作系统的内存资源)
       # print(f)
      data=f.read()                  #读写操作
      f.close()                     #向操作系统发送信号,让操作系统关闭打开的文件,从而回收操作系统的资源

    上下文管理:(使用这种打开方式不用自己去关闭文件,在程序结束时会自动关闭文件
    with open(r'c.txt',mode='r',encoding='utf-8') as f,open(r'b.txt',mode='r',encoding='utf-8') as f1:
        读写文件的操作
        pass
    大前提: tb模式均不能单独使用,必须与纯净模式结合使用

    操作文件内容的模式:t(默认),b
      t(默认的):操作文件内容都是以字符串为单位,会自动帮我们解码,必须指定encoding参数(解码时候没人告诉计算机用什么解码,而window系统默认是GBK编码,所以要指定)
      b: 操作文件内容都是以Bytes(二进制)为单位,硬盘中存的时什么就取出什么,一定不能指定encoding参数
    t文本模式:
      1. 读写文件都是以字符串为单位的
      2. 只能针对文本文件
      3. 必须指定encoding参数
    b二进制模式:
      1.读写文件都是以bytes/二进制为单位的
      2. 可以针对所有文件
      3. 一定不能指定encoding参数
      总结:t模式只能用于文本文件,而b模式可以用于任意文件(如图片,视频,文本)

    文件打开的三种纯净模式:r(默认的) w a

    一、r模式:只读模式,在文件不存在时则报错,如果文件存在文件指针跳到文件的开头
    with open(r'c.txt',mode='rt',encoding='utf-8') as f:(红色r代表原生字符,没有转义,可以避免
    被当成换行符号print(f.read())
        print(f.readable())
        print(f.writable())
        f.write('hello') # 报错,只能读
    
        data=f.read()
        print(data,type(data))#str
    with open(r'c.txt',mode='rb') as f:
        data=f.read()             #b模式
        print(data,type(data))       #b'jinrui:123
    xuechengeng:12345
    egon:1234
    alex:alex123' <class 'bytes'>
        res=data.decode('utf-8')
        print(res)
    
    
    with open(r'c.txt',mode='rt',encoding='utf-8') as f:
        line=f.readline()
        print(line,end='')
        line1=f.readline()      #一行一行的读,读完文件没有关闭的话,指针会跳到下一行的开头;如果文件关闭的话指针重新回到起点。
        print(line1,end='')
        line2 = f.readline()
        print(line2,end='')
    
        lines=f.readlines()     #一次读多行
        print(lines)

     循环读文件内容的方法:

    with open(r'c.txt',mode='rt',encoding='utf-8') as f:  #f是文件对象
        for line in f:
            print(line,end='*')
        #  egon:123
          *alex:456
          *lxx:789*        #正常的 有换行,print也有换行,但是end('=')覆盖了 ,

     二、w模式:只写模式 在文件不存在时会创建空文档,文件存在会清空文件,文件指针跑到文件开头

    with open('b.txt',mode='wt',encoding='utf-8') as f:
        print(f.writable())
        print(f.readable())
        f.write('你好
    ')
        f.write('我好
    ') # 强调:在文件不关闭的情况下,后写的内容一定跟着前写内容的后面
        f.write('大家好
    ')
        f.write('111
    222
    333
    ')
    
        lines=['1111','22222','33333']
        for line in lines:
            f.write(line)  #11112222233333。没有
    不会换行;
        f.writelines(lines)  #不是写很多行的意思,而是上面for循环的简写模式,没有
    不会换行
    三、a模式:只追加写模式 在文件不存在时会创建空文档,文件存在会将文件指针直接移动到文件末尾,追加内容

    # r+ w+ a+,读写模式
    with open('a.txt',mode='r+t',encoding='utf-8') as f:
        print(f.readable())
        print(f.writable())
        print(f.readline())
        f.write('你好啊')
    with open('d.txt','wb') as f:
        f.write('你好'.encode('gbk'))  #在d.txt文件中写入‘你好’,用gbk编码,所以要查看必须用gbk模式查看

    实现功能代码:
    注册:

    1 name = input('用户名:')
    2 pwd = input('密码:')
    3 with open('db.txt',mode='at',encoding='utf-8') as f:
    4     info = '%s:%s
    '%(name,pwd)
    5     f.write(info)
    6     print('注册成功')
    View Code
    登录:
     1 # coding:utf-8
     2 name = input('请输入用户名:>').strip()
     3 pwd = input('请输入密码:>').strip()
     4 with open(r'c.txt', mode='rt', encoding='utf-8') as f:
     5     for line in f:
     6         n, p = line.strip('
    ').split(':')
     7         if name == n and pwd == p:
     8             print('登录成功')
     9             break
    10     else:
    11         print('账号或密码错误')
    View Code
    拷贝文件:
    1 src_file=input('源文件路径:')
    2 drc_file=input('目标路径:')
    3 with open(r'%s'%src_file,mode='rb') as f,open(r'%s'%drc_file,mode='wb') as f1:
    4     for line in f:
    5         f1.write(line)
    View Code

     指针移动:

    大前提:文件内指针的移动是Bytes为单位的,唯独t模式下的read(不是r模式)读取内容个数是以字符为单位

    文本读取模式:

    with open('a.txt',mode='rt',encoding='utf-8') as f:
        data=f.read(3)    #从开头读取三个字符
        print(data)

    字节读取模式:

    with open('a.txt',mode='rb') as f:
        data=f.read(3)    #从开头读取三个字节
        print(data.decode('utf-8'))
    f.seek(指针移动的字节数,模式控制): 控制文件指针的移动,都是以字节为单位
    模式控制:
      0: 默认的模式,该模式代表指针移动的字节数是以文件开头为参照的
      1: 该模式代表指针移动的字节数是以当前所在的位置为参照的
      2: 该模式代表指针移动的字节数是以文件末尾的位置为参照的
    强调:其中0模式可以在t或者b模式使用,而1跟2模式只能在b模式下用
      f.tell()查看文件指针当前距离文件开头的位置

      # 0模式详解:文件开头

    a.txt文件第一行内容:你a我擦嘞111
    with open('a.txt',mode='rt',encoding='utf-8') as f:
        f.seek(4,0)      #从文件开头,读取四个字节
        print(f.tell())
        print(f.read())    #从4开始往后读完

    with open('a.txt',mode='rb') as f:
    f.seek(4,0)
    # f.seek(2,0)    #报错,因为没有完整截到一个字符你,在decode时会报错
    print(f.tell())
    print(f.read().decode('utf-8'))

    with open('a.txt',mode='rt',encoding='utf-8') as f:
    f.seek(5,0)     #5将我拆分了
    print(f.read())  #报错,t模式下的read是以字符为单位
     # 1模式详解:当前位置
    with open('a.txt',mode='rb') as f:
        f.seek(3,1)
        print(f.tell())  #3
        f.seek(4,1)     
        print(f.tell())  #7,正好是我字结束
        print(f.read().decode('utf-8'))  #可以正常打印
    # 2模式详解:
    with open('a.txt',mode='rb') as f:
        f.seek(-9,2)      #-9是向前移动九位
        data=f.read()
        print(data.decode('utf-8'))
    打印登录日志:
    # tail -f access.log
    with open('access.log',mode='rb') as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if len(line) == 0:
                # 没有内容
                continue
            else:
                print(line.decode('utf-8'),end='')
    文件的修改:
    须知一:
      硬盘空间无法修改,硬盘中的数据更新都是用新的内容覆盖旧的内容
      内存内容可以修改
    硬盘上直接覆盖:
    with open('a.txt','r+t',encoding='utf-8') as f:   f.seek(4,0)   print(f.tell())   f.write('我擦嘞') #是直接将原位上的数据覆盖了,不存在插入
    须知二:
      文件对应的是硬盘空间,硬盘不能修改因为文件本质也不能修改

    我们看到文件的内容可以修改,是如何实现的呢?
      大的的思路:将硬盘中文件内容读入内存,然后在内存中修改完毕后再覆盖回硬盘

    修改文件的两种方式:
    1. 将文件内容发一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
      优点: 在文件修改过程中同一份数据只有一份
      缺点: 会过多地占用内存,如果文件过大,会造成内存溢出
    with open('db.txt',mode='rt',encoding='utf-8') as f:
        data=f.read()
    
    with open('db.txt',mode='wt',encoding='utf-8') as f:
        f.write(data.replace('kevin','SB'))
    2. 以读的方式打开原文件,以写的方式打开一个临时文件,按行读取原文件内容,修改完后写入临时文件...,删掉原文件,将临时文件命名为原文件名
      优点: 不会占用过多的内存
      缺点: 在文件修改过程中同一份数据存了两份
    import os
    with open('db.txt',mode='rt',encoding='utf-8') as read_f,
            open('.db.txt.swap',mode='wt',encoding='utf-8') as wrife_f:
        for line in read_f:#读一行
            wrife_f.write(line.replace('SB','kevin'))#改一行,然后写进去
    os.remove('db.txt')
    os.rename('.db.txt.swap','db.txt')
     
  • 相关阅读:
    C++ P1890 gcd区间
    C++ P1372 又是毕业季I
    C++ CF822A I'm bored with life
    C++ P4057 [Code+#1]晨跑
    C++ CF119A Epic Game
    关于树状数组的几点总结
    markdown语法
    portal开发"下拉框"“日期框”查询要怎么配置
    泛型总结--待续
    Actioncontext跟ServletActionContext的区别---未完待续
  • 原文地址:https://www.cnblogs.com/xuechengeng/p/9675772.html
Copyright © 2011-2022 走看看