diff --git "a/src/28.\345\255\227\347\254\246\351\233\206\345\222\214\345\255\227\347\254\246\347\274\226\347\240\201.md" "b/src/28.\345\255\227\347\254\246\351\233\206\345\222\214\345\255\227\347\254\246\347\274\226\347\240\201.md"
new file mode 100644
index 0000000..9547f26
--- /dev/null
+++ "b/src/28.\345\255\227\347\254\246\351\233\206\345\222\214\345\255\227\347\254\246\347\274\226\347\240\201.md"
@@ -0,0 +1,91 @@
+## 楔子
+
+接下来我们将分析 Python 的字符串,这应该是使用频率最高的数据结构了,我们会通过多篇文章来详细阐述字符串的实现原理。
+
+首先字符串是一个变长对象,因为不同长度的字符串所占的内存是不一样的。但同时字符串又是一个不可变对象,因为一旦创建就不可以再修改了。
+
+## 多字节编码
+
+我们知道计算机的存储单位是字节,一个字节可以表示 256 种字符,对于发明计算机的美国人来说足够了。因为英文字母算上大小写只有 52 个,即便再加上一些特殊字符,数量也不会超过 256 个,因此一个字节完全可以表示。
+
+但随着计算机的普及,越来越多的非英文字符出现,导致一个字节已经无法表示了。所以只能曲线救国,对于一个字节无法表示的字符,使用多个字节表示,这便是多字节编码。而多字节编码也存在相应的问题,就是容易出现乱码。
+
+到这里先不继续往下深入,我们先来理清楚一些概念。
+
+## 字符集和字符编码
+
+估计有很多小伙伴搞不清这两者的区别,我们先来解释一下所谓的字符集和字符编码是怎么一回事?
+
++ 字符集:系统支持的所有字符组成的集合,像 ASCII、GB2312、Big5、unicode 都属于字符集。只不过不同的字符集所能容纳的字符个数不同,比如 ASCII 字符集不包含中文,unicode 则可以容纳世界上的所有字符;
++ 多字节编码:负责将每个字符转成一个或多个计算机可以接受的具体数字,该数字可以理解为编号,因此字符编码维护了字符和编号之间的对应关系。而编码也分为多种,比如 ASCII、GBK、UTF-8 等等,字符编码不同,那么字符转换之后的编号也不同,当然能转化的字符种类也不同。比如 ASCII 这种字符编码,它就只能转换 ASCII 字符。
+
+当然,ASCII 比较特殊,它既是字符集、也是字符编码。并且不管采用什么编码,ASCII 字符对应的编号永远是相同的。
+
+将字符串中的每一个字符转成对应的编号,那么得到的就是字节序列(bytes 对象),因为计算机存储和网络通讯的基本单位都是字节,所以字符串必须以字节序列的形式进行存储或传输。
+
+因此字符串和字节序列在某种程度上是很相似的,字符串按照指定的编码进行 encode 即可得到字节序列,也就是将每个字符都转成对应的编号;字节序列按照相同的编码 decode 即可得到字符串,也就是根据编号找到对应的字符。
+
+比如我们写了一段文本,然后在存储的时候必须先进行 encode,也就是将每一个字符都转成一个或多个系统可以接受的数字、即对应的编号之后,才可以进行存储。
+
+~~~Python
+name = "古明地觉"
+
+print(name.encode("gbk"))
+"""
+b'\xb9\xc5\xc3\xf7\xb5\xd8\xbe\xf5'
+"""
+print(name.encode("utf-8"))
+"""
+b'\xe5\x8f\xa4\xe6\x98\x8e\xe5\x9c\xb0\xe8\xa7\x89'
+"""
+~~~
+
+采用不同的编码,得到的字节序列是不同的,比如使用 gbk 编码 encode,那么也必须使用 gbk 编码 decode。否则会因为无法解析而报错,因为字符编码不同,字符对应的编号也不同。
+
+再比如每个国家都有自己的字符编码,你在日本的一台计算机上写好的文件拿到中国的计算机上打开,很有可能出现乱码。因为字符编码不同,字符和编号之间的对应关系也不同,采用不同的字符编码进行解析肯定会出问题。
+
+但我们说,对于 ASCII 字符来说,由于不管采用哪一种编码,它们得到的编号都是固定的。所以编码对于 ASCII 字符来说,没有任何影响。
+
+~~~Python
+name = "satori"
+
+print(name.encode("gbk"))
+"""
+b'satori'
+"""
+print(name.encode("gbk").decode("utf-8"))
+"""
+satori
+"""
+
+# 但如果是非 ASCII 字符,就不行了
+try:
+ "你好".encode("gbk").decode("utf-8")
+except UnicodeDecodeError as e:
+ print(e)
+ """
+ 'utf-8' codec can't decode byte 0xc4 in position 0: invalid continuation byte
+ """
+~~~
+
+这里再回忆一下 bytes 对象,创建的时候可以采用字面量的方式,比如 b"abc",但是 b"憨" 却不可以。原因就是憨这个字符不是 ASCII 字符,那么采用不同的字符编码,其对应的编号是不同的。而解释器又不知道我们使用的是哪一种编码,所以不允许这么做,而是需要通过 "憨".encode() 的方式手动指定字符编码。
+
+但对于 ASCII 字符而言,不管采用哪一种字符编码,得到的编号都是一样的, 所以 Python 针对 ASCII 字符则允许这种做法,比如 b"abc"。并且我们看到,对于汉字来说,在编码之后会对应多个编号,而每个编号占 1 字节,因此不同的字符所占的大小可能不同。
+
+## 小结
+
+以上就是字符集和字符编码,字符集就是字符组成的集合,不同字符集所能容纳的字符数量是有限的。字符编码是将字符转成对应的编号,比如将一个字符串中的所有字符都转成对应的编号之后,就得到了字节序列。当然和字符集一样,字符编码能转换的字符种类也是有限的,像汉字我们可以使用 GBK 编码、UTF-8 编码,但是不能使用 ASCII 编码。
+
+以上算是理清楚了一些概念,显然过于简单了,主要是为后面的内容做铺垫。那么下一篇文章,我们就从 Python 的角度来分析字符串的存储方式。
+
+----------------
+
+
+
+**欢迎大家关注我的公众号:古明地觉的编程教室。**
+
+![](./images/qrcode_for_gh.jpg)
+
+**如果觉得文章对你有所帮助,也可以请作者吃个馒头,Thanks♪(・ω・)ノ。**
+
+![](./images/supports.png)
\ No newline at end of file
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 7dc0bc7..2c2f8b0 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -27,4 +27,5 @@
+ [24. bytes 对象都支持哪些操作,它们是怎么实现的?](24.bytes对象都支持哪些操作,它们是怎么实现的?.md)
+ [25. 通过 bytes 对象的合并,探究缓冲区的奥秘](25.通过bytes对象的合并,探究缓冲区的奥秘.md)
+ [26. 解密 bytes 对象的缓存池](26.解密bytes对象的缓存池.md)
-+ [27. 详解 bytearray 对象的底层实现](27.详解bytearray对象的底层实现.md)
\ No newline at end of file
++ [27. 详解 bytearray 对象的底层实现](27.详解bytearray对象的底层实现.md)
++ [28. 字符集和字符编码](28.字符集和字符编码.md)
\ No newline at end of file