字符编码

发布时间 2023-12-11 14:05:26作者: 蓝幻ﹺ

什么是字符编码

  • 字符编码中的编码指的是翻译或者转换的意思
  • 即将人能理解的字符翻译成计算机能识别的数字

字符编码的发展史

一家独大

  • 计算机是美国人发明的,
  • 美国人想更方便的掌控计算机中的语言,于是就发明了ASCII码表
    • 这张表存储了英文字符及特殊标点和数字之间的一一对应关系
  • 一个英文字符是一个比特位,bytes
    • 计算机能识别的就是二进制编码
      • 0 / 1
    • 1B=8Bytes ---> 256种 2**8
    • A-Z:65-90
    • a-z:97-122
    • 0-9:48-57

诸侯割据

  • 随着计算机的发展和普及,各个国家都想有一张自己国家语言对应的编码表,于是就诞生了gbk,SHIFT-jis
  • 美国人想用中国人开发的软件,中国人开发的软件的编码是按照GBK编码的,但是美国人没有GBK
    • 一种国家编码的软件就需要对应一个国家的编码表

一统天下

  • Unicode编码表
  • 这张表包括了万国码,
    • 英文字符对应着一个编码
    • 中文字符也对应着一个编码
    • 日文也发对应着一个编码

UTF-8

  • Unicode格式的二进制存储到硬盘的时候可能会占用更多的空间
  • 为了节省字符占用的内存空间
    • 于是就想到了一种新的编码格式,utf-8
  • 将我们的英文/中文/日文 --->内存中(unicode编码二进制) ---> 硬盘(utf-8编码)

编码和解码的方式

# 编码 --- 指定编码格式
name = 'dream'
name = '国'
age = 1
print(name.encode('utf-8'))
# b'\xe5\x9b\xbd'

# 解码 --- 按照编码的编码类型去解码
# bytes
name_b = b'dream'
name_b = b'\xe5\x9b\xbd'
print(name_b.decode('utf-8'))

字符编码的目的

  • 为了你的字符不会变成乱码

    • 读出来是乱码
    • 写进去是乱码
  • 文件操作的三种方式

    • w
    • a
    • r
  • 文件操作的操作方法

    • f
      • read
      • readline
      • readlines
    • w
      • write
      • writeline
      • writelines
  • 主动控制文件指针

  • 异常处理

    • 捕获程序中的异常
    • try --- except
    • try --- finally
    • try --- else
    • assert

【一】操作文件的两种方式

# 【一】文件操作的方式一
# 将文件以指定编码格式打开,将文件句柄交给 变量 fp
# fp = open('01.txt', 'w', encoding='utf-8')
# 用句柄去操作文件
# w r a
# fp.write('my age is 18')
# 关闭文件
# fp.close()

# 【二】文件操作方式二
# Python解释器内置了一个文件操作器 --- 能自主的回收系统资源 --- with 语句
# with open('01.txt', 'w', encoding="utf8") as fp:
#     fp.write("my name is dream")

【二】文件操作的三种方式

# 【三】操作文件的三种方式
# w(write) 模式 : write 覆盖写模式,如果你文件中有内容,直接覆盖掉写进去新的内容
# 如果不存在该文件,则会创建一个新的文件,然后再向文件中写新的内容进去
# with open('01.txt', 'w', encoding='utf-8') as fp:
#     fp.write('my name is hope')

# a(append) 模式 : write 追加写模式,如果你文件中有内容,再原有内容的基础上追加内容
# 如果不存在该文件,则会创建一个新的文件,然后再向文件中写新的内容进去
# with open('01.txt', 'a', encoding="utf8") as fp:
#     fp.write('my age is 18' + '\n')
#     fp.write('你最帅啦!' + '\n')
#     fp.write('my name is hope')

# r(read) 模式 : read 读内容模式,可以将文件中的内容读出来
# with open('01.txt', 'r', encoding='gbk') as fp:
#     data = fp.read()
#     print(data)
# my age is 18
# my name is dream
# my name is hope
# 浣犳渶甯呭暒!

# 提示 : 写文件内容时,用的什么编码,读文件时就要用指定编码进行读
# with open('01.txt', 'r', encoding='utf-8') as fp:
#     data = fp.read()
#     print(data)

# my age is 18
# my name is dream
# my name is hope
# 你最帅啦!

【三】控制文本读写格式

# 【四】控制文件读写内容的模式

# t 模式 : 文本类型。读内容和写内容都是字符串格式
# name = "my name is dream"
# with open('01.txt', 'wt', encoding='utf8') as fp:
#     fp.write(str(name))
# name = [1, 2, 3]
# name = {'name': "dream"}
# with open('01.txt', 'at', encoding='utf8') as fp:
#     fp.write(str(name) + '\n')

# 特别注意 :读出来的内容是字符串格式,即使长得像列表,其实也是字符串格式
# with open('01.txt', 'rt', encoding='utf8') as fp:
#     data = fp.read()
#     print(data, type(data))
#     for data in data.split('\n'):
#         print(list(data), type(list(data)))

# [1, 2, 3]
# {'name': 'dream'}
#  <class 'str'>
# ['[', '1', ',', ' ', '2', ',', ' ', '3', ']'] <class 'list'>
# ['{', "'", 'n', 'a', 'm', 'e', "'", ':', ' ', "'", 'd', 'r', 'e', 'a', 'm', "'", '}'] <class 'list'>
# [] <class 'list'>

# b 模式 :二进制模式。读内容和写进去的内容必须都是二进制格式
# with open('girl.jpg','rb') as fp:
#     data = fp.read()
#     print(data)
# import requests
# 
# response = requests.get('https://pic.netbian.com/uploads/allimg/231201/005415-17013632559ae8.jpg')
# data = response.content
# # 图片格式 : png / jpeg / jpg / webp  --- 文件后缀名,txt
# # img : image 图片的英文单词 我们习惯用img/image来命名图片文件夹
# with open('wait.png', 'wb') as fp:
#     fp.write(data)

【四】文件拷贝练习

# 小练习
# 编写文件拷贝工具
# 输入一个文件地址 --- 把文件内容读出来
# 输入一个文件地址 --- 把当前文件内容拷贝到新的地址和新的文件里面

# 旧地址:D:\Python\PythonProjects28\day10\girl.jpg
# 新地址:D:\Python\PythonProjects28\day10\img\girl.jpg

# path_start = input("原始地址:>>>>").strip()
# path_end = input("目标地址:>>>>").strip()
# modle = {1: 'wb', 2: 'rb'}
# print(f"{path_start} to {path_end} :>>>> 已开始!")
# with open(path_start, modle[2]) as read_f, open(path_end, modle[1]) as write_f:
#     write_f.write(read_f.read())
#     print(f"{path_start} to {path_end} :>>>> 已完成!")

【五】文件操作方法详细

【1】读操作

# 【五】文件操作的详细用法
# 【1】read相关
# read 方法 : 一次性将文件中的所有内容读出来
# with open('01.txt', 'r', encoding='utf-8') as fp:
#     data = fp.read()
#     print(data)
#     # [1, 2, 3]
#     # {'name': 'dream'}

# readline :只读一行
# with open('01.txt', 'r', encoding='utf-8') as fp:
#     data = fp.readline()
#     print(data)
#     data = fp.readline()
#     print(data)
#     for line in fp:
#         print(line)
#     # [1, 2, 3]
#     #
#     # {'name': 'dream'}

# readlines : 将文件中的每一行内容读出来,读出来以后放到一个列表中
# with open('01.txt', 'r', encoding='utf-8') as fp:
#     data = fp.readlines()
#     print(data)
#     # ['[1, 2, 3]\n', "{'name': 'dream'}\n"]

【六】控制文件内光标移动

# 【七】控制文件内的指针移动

# 【1】控制读的字符个数
# 控制读数据时,读出来的字符个数
# with open('01.txt', mode='rt', encoding='utf-8') as f:
#     data = f.read(6)  # 读取3个字符
#     print(data)

# 【2】seek方法
# 如果我们想读取文件内容指定位置的内容,就需要使用 seek 函数来让我们的指针移动到指定位置

# seek : 三种模式 :
# 0 : 以文件开头作为参照
# 1 : 以当前我所在位置作为参照
# 2 : 以文件末尾的位置作为参照

# 【3】 0 模式 :以文件开头作为参照
# with open('02.txt', 'rt', encoding='utf-8') as fp:
#     # 英文占一个字节 (一个字符)
#     # 中文占三个字节 (一个字符)
#     fp.seek(6, 0)
#     print(fp.tell())  # 6
#     print(fp.read())  # 从开头开始算,移动6个字节,再从6字节这个位置向后读数据

# 【4】1 : 以当前我所在位置作为参照
# with open('02.txt', 'rb') as fp:
#     # 英文占一个字节 (一个字符)
#     # 中文占三个字节 (一个字符)
#     # print(fp.read())
#     fp.seek(3, 1)
#     print(fp.tell())  # 3
#     # print(fp.read())  # 从当前算,移动3个字节
#     r'''
#     name = b'\xe4\xbd\xa0\xe7\x9c\x9f\xe5\xb8\x85!'
#     print(name.decode('utf8'))
#     # 你真帅!
#     '''
#     fp.seek(3, 1)
#     print(fp.tell())  # 6
#     print(fp.read())  # 在上面光标 (3)的位置基础上,再移动三个字节,
#     r'''
#     name = b'\xe7\x9c\x9f\xe5\xb8\x85!'
#     print(name.decode('utf-8'))
#     # 真帅!
#     '''

# 【5】2 : 以文件末尾的位置作为参照
# with open('02.txt', 'rb') as fp:
#     # 英文占一个字节 (一个字符)
#     # 中文占三个字节 (一个字符)
#     # print(fp.read())
#     # 移动光标在文件结尾
#     # fp.seek(0, 2)
#     # print(fp.tell()) # 13
#     # 倒着取,从结尾向前移动
#     fp.seek(-4, 2)
#     print(fp.read())

【七】文件内容替换练习

# 【练习】
# with open('03.txt', 'r', encoding='utf-8') as fp:
#     # print(fp.read()) # ABCDEFGHIJKLMN
#     fp.seek(3, 0)
#     print(fp.read())  # DEFGHIJKLMN

# 原来的文本内容如下
# 张一蛋     山东    179    49    12344234523
# 李二蛋     河北    163    57    13913453521
# 王全蛋     山西    153    62    18651433422

# 修改后的内容如下
# 张一蛋(妇女主任)  山东    179    49    12344234523
# 李二蛋(村长)     河北    163    57    13913453521
# 王全蛋(书记)     山西    153    62    18651433422

# 纠正下述代码
# with open('04.txt', 'r+', encoding='utf-8') as fp:
#     fp.seek(9)
#     fp.write('(妇女主任阿萨阿萨撒啊飒飒)')

with open('04.txt', 'r', encoding='utf-8') as file:
    data = file.readlines()

line_list = []
for line in data:
    if '张一蛋' in line:
        line = line.replace(line.split()[0], f'{line.split()[0]}(妇女主任)')
    elif '李二蛋' in line:
        line = line.replace(line.split()[0], f'{line.split()[0]}(村长)')
    elif '王全蛋' in line:
        line = line.replace(line.split()[0], f'{line.split()[0]}(书记)')
    line_list.append(line)
print(line_list)
with open('04.txt', 'w', encoding='utf-8') as fp:
    fp.writelines(line_list)

【八】列表生成式

# num_list = []
# for i in range(0, 10):
#     num_list.append(i)
# print(num_list)

# # 列表生成式
# # print([i for i in range(0, 10)])
#
# # 原始列表 : 每个元素都有空格
# some_animals = [' dog', 'cat  ', ' sheep ']
# # some_animals_new = []
# # for i in some_animals:
# #     i = i.strip()
# #     some_animals_new.append(i)
# # print(some_animals_new)
# # 列表生成式: 新的列表,每个元素都去除掉了空格
# some_animals = [i.strip() for i in some_animals]
# print(some_animals)
# # ['dog','cat','sheep']

# test_1 = [1, 2, 3]
# test_2 = [4, 5, 6]
#
# new_list = []
# for j in test_1:
#     for k in test_2:
#         num = j*k
#         new_list.append(num)
# print(new_list)
#
# # 列表生成式 : 遍历两个列表并取出每一个列表的元素 做乘法运算
# list_one = [x * y for x in test_1 for y in test_2]
# print(list_one)
# # [4,5,6,8,10,12,12,15,18]

test_1 = [1, 2, 3]
test_2 = [4, 5, 6]
# # 列表生成式 : 遍历两个列表并取出每一个列表的元素 做新列表的生成
# list_two = [(x, x + y) for x in test_1 for y in test_2]
# print(list_two)
# # [[1, 5], [1, 6], [1, 7], [2, 6], [2, 7], [2, 8], [3, 7], [3, 8], [3, 9]]

# for i in range(len(test_1)):
#     num = test_1[i] * test_2[i]

# 列表生成式 : 遍历两个列表并取出每一个列表对应索引的元素 做乘法运算
# list_three = [test_1[i] * test_2[i] for i in range(len(test_1))]
# print(list_three)
# # [4, 10, 18]

# test_1 = [1, 2, 3]
# test_2 = [4, 5, 6]
#
# for k, j in zip(test_1, test_2):
#     print(k, j)
#
# # 列表生成式 : 遍历两个列表并取出每一个列表对应索引的元素 做乘法运算
# list_four = [x * y for x, y in zip(test_1, test_2)]
# print(list_four)
# [4, 10, 18]

# 字典生成式

# num_dict = {}
# for key in range(3):
#     for value in range(2):
#         num_dict[key] = value
#
# print(num_dict)
#
# my_dict = {key: value for key in range(3) for value in range(2)}
# print(my_dict)
# # {0: 1, 1: 1, 2: 1}

(1)新生成列表的每个元素都可以是任意的表达式或对象

test = [1, 2, 3]

print([i * i for i in test])
# [1,4,9]

print([[i, i + 2] for i in test])
# [[1,3],[2,4],[3,5]]

(2)让每个元素执行相同的操作

# 原始列表 : 每个元素都有空格
some_animals = [' dog', 'cat  ', ' sheep ']

# 列表生成式: 新的列表,每个元素都去除掉了空格
some_animals_new = [i.strip() for i in some_animals]
print(some_animals_new)
# ['dog','cat','sheep']

(3)加入嵌套循环

test_1 = [1, 2, 3]
test_2 = [4, 5, 6]

# 列表生成式 : 遍历两个列表并取出每一个列表的元素 做乘法运算
list_one = [x * y for x in test_1 for y in test_2]
print(list_one)
# [4,5,6,8,10,12,12,15,18]

# 列表生成式 : 遍历两个列表并取出每一个列表的元素 做新列表的生成
list_two = [[x, x + y] for x in test_1 for y in test_2]
print(list_two)
# [[1, 5], [1, 6], [1, 7], [2, 6], [2, 7], [2, 8], [3, 7], [3, 8], [3, 9]]

###  注意通过这两个print体会谁是内层循环,谁是外层循环

# 列表生成式 : 遍历两个列表并取出每一个列表对应索引的元素 做乘法运算
list_three = [test_1[i] * test_2[i] for i in range(len(test_1))]
print(list_three)
# [4, 10, 18]

# 列表生成式 : 遍历两个列表并取出每一个列表对应索引的元素 做乘法运算
list_four = [x * y for x, y in zip(test_1, test_2)]
print(list_four)
# [4, 10, 18]

【九】字典生成式

  • 有了列表推导式的概念,字典推导式学起来就非常简单了,语法格式如下:
{键:值 for 迭代变量 in 可迭代对象 [if 条件表达式]}