前言

其实,这是一个老生常谈的问题。 相信当你第一次遇到编码问题时,你一定会去网上搜索。

找了几个解释,虽然有点乱,但还是觉得明白了一些东西,然后继续说其他的东西。

之所以专门针对这个问题写一篇文章,是因为前两天接触到了一位在公司有十几年工作经验的JAVA程序员。

使用API​​时,我问他返回的汉字是什么编码,他回答“直接返回”。 这么有经验的老程序员

我对这个基本问题了解不多,所以我觉得有必要仔细解释一下这个问题。

字符

在介绍它们之间的区别时,我们先来说说它们是什么。 简单来说,就是一个字符集(set)。

与ASCII一样,它的功能是用一系列数字来表示字符()。 这些数字有时称为代码点(代码)。

当PC刚问世时,几位使用英语的先驱认为,计算机需要表示的字符并不多,26个英文字母加上一些回车、换行等。

特殊符号,总共一百个字符是压倒性的,所以就有了ASCII。 ASCII码的大小为1字节,定义了128个字符。

分别表示为0-127。 例如,字符“A”的码位为65,回车符“n”的码位为10,如下所示:

当然,后来人们发现世界上的字符远不止128个,所以需要一个新的字符集来表示世界上所有的字符。

包括一个英文字符、一个汉字、一个象形文字等。这个字符集是。 向前兼容 ASCII,

它最多可以表示2^21(约200万)个字符,足以覆盖当今所有国家的文字,如下图:

当前字符集表示完所有字符后,还剩下一些字符。 这些暂时未使用的部分通常由占位符 FFFD 表示。

字符编码

有了字符集,我们现在可以使用任何数字来表示现实生活中的字符。 但在将字符保存到计算机之前,必须先对它们进行编码。

有人问,把数字直接存到内存里不就可以了吗? 但是用多少字节来表示一个数字以及每个字节的范围都是有要求的

事先约定好,这种约定称为编码。 假设我们有四个数字1、2、3、4要存储在计算机中,如果约定utf-8编码,

那么在内存中的表示如下:

00000001 00000010 00000011 00000100

其他编码规则包括utf-16、gbk等,具体编码规则超出了本文的范围。 如果你想了解更多,可以上网查看相关文档。

因此,我们可以看到,如果不按照约定的规则进行解码,很有可能无法恢复出原始数据,这就是我们经常遇到的“乱码”。

下面举几个例子简单说明一下:

>>> u'你好'
u'u4f60u597d'
>>> u'你好'.encode('utf8')
'xe4xbdxa0xe5xa5xbd'
>>> u'你好'.encode('gbk')
'xc4xe3xbaxc3'
>>> u'你好'.encode('utf8').decode('gbk')
u'u6d63u72b2u30bd'
>>> print u'你好'.encode('utf8').decode('gbk')
浣犲ソ

如上面代码所示,“Hello”两个汉字分别为4f60和597d,utf-8编码占用6个字节,gbk编码占用4个字节。

如果用utf8编码后误用gbk解码,会得到3个码点,分别代表字符huan、e、ソ; 如果你用gbk编码

如果错误地使用utf8进行解码,将无法获得足够的3个字节来解码第二个字符,因此会得到未知的结果,甚至会因内存越界访问而导致程序异常。

注意:本文中的代码示例在Linux下运行,因此默认编码为UTF-8。 如果你在cmd中运行,默认编码是GBK,所以不同地方会出现乱码:)

了解了字符编码和解码的用法之后,我们就可以解释一些常见的乱码的由来了。 例如,未初始化的堆栈将被初始化为0xcc,未初始化的堆内存将被初始化为0xcd。 可以看到前者是 'hot' 的 gbk 编码,而后者恰好是 'Tun' 的 gbk 编码,如下图:

u'ufffd'
>>> u'烫'
u'u70eb'
>>> u'烫'.encode('gbk')
'xccxcc'
>>> u'屯'
u'u5c6f'
>>> u'屯'.encode('gbk')
'xcdxcd'

正如前面提到的,暂时不使用的代码点将由占位符 FFFD 表示。 如果这个占位符解析错误,它将被视为有意义的内容:

>>> u'uFFFD'.encode('utf8')
'xefxbfxbd'
>>> u'锟斤拷'.encode('gbk')
'xefxbfxbdxefxbfxbd'
>>> print (u'uFFFD'.encode('utf8')*2).decode('gbk')
锟斤拷

可以看出,汉字“·”()的gbk编码分别是xefxbf、xbdxef和xbfxbd,它们正是FFFD码的utf8编码的叠加,所以如果你遇到多个 utf8 编码的占位符并且不幸使用 gbk 方法进行解码,那么你就会看到熟悉的坤金手铐。

其他

在.exe中可以看到保存的文件格式如下:

gbk编码_汉字转gbk编码_gbk码的编码原理

但你刚才不是说这只是一个字符集吗? 为什么显示可以另存为“编码”? 好吧,这实际上是一个该死的名字。

地方。 因为UTF-16 (UTF-16LE)是内部使用的默认编码,并且这被认为是标准的编码格式

有ANSI字符串(在当前系统代码页中,不可扩展)和字符串(内部以UTF16-LE编码存储)。 因此,

大端,其实就是UTF16-BE。

这其实并不奇怪,因为这是在出现初期设计的,当时我们还没有意识到UCS-2的缺点,而且UTF-8还没有被发明出来。 这就是为什么对 UTF8 的支持如此之差。 原因之一。

后记

说了这么多,现在让我们回到最初的问题。 如果有人问你“GBK和UTF-8有什么区别?”,我想你应该知道如何回答:它是一种字符集,而GBK和UTF-8都是编码,所以它们不一样后两者,不能相提并论。

博客地址:

好了,今天的主题就讲到这里吧,不管如何,能帮到你我就很开心了,如果您觉得这篇文章写得不错,欢迎点赞和分享给身边的朋友。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注