美文网首页
搞定编码格式问题

搞定编码格式问题

作者: shuaiutopia | 来源:发表于2019-06-01 16:16 被阅读0次

Unicodeutf-8

以下文章来自知乎回答

Unicode 是「字符集」
UTF-8 是「编码规则」

其中:

字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)
编码规则:将「码位」转换为字节序列的规则(编码/解码 可以理解为 加密/解密 的过程)

广义的 Unicode 是一个标准,定义了一个字符集以及一系列的编码规则,即 Unicode 字符集和 UTF-8、UTF-16、UTF-32 等等编码……
Unicode 字符集为每一个字符分配一个码位,例如「知」的码位是 30693,记作 U+77E5(30693 的十六进制为 0x77E5)。
UTF-8 顾名思义,是一套以 8 位为一个编码单位的可变长编码。会将一个码位编码为 1 到 4 个字节:

    U+ 0000 ~ U+ 007F : 0XXXXXXX   
    U+ 0080 ~ U+ 07FF : 110XXXXX 10XXXXXX   
    U+ 0800 ~ U+ FFFF : 1110XXXX 10XXXXXX 10XXXXXX   
    U+10000 ~ U+1FFFF : 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX   

根据上表中的编码规则,之前的「知」字的码位 U+77E5 属于第三行的范围:

    7    7    E    5         
    0111 0111 1110 0101  二进制的 77E5 
    --------------------------     
    1110XXXX 10XXXXXX 10XXXXXX 模版(上表第三行,X的个数为 4 6 6)即讲77E5的 0111011111100101按长度4 6 6 截取
    0111   011111   100101 二进制的 77E5 (unicode统一用两个字节byte即16位bit来表示所有字符)
    11100111 10011111 10100101 代入模版    
      E 7       9 F     A 5 
      
# 帅的 Unicode编码16进制为 5E05      
    5    E    0    5         
    0101 1110 0000 0101  二进制的 5E05
    --------------------------     
    1110XXXX 10XXXXXX 10XXXXXX 模版(上表第三行,X的个数为 4 6 6)即讲77E5的 0111011111100101按长度4 6 6 截取
    0101   111000   000101 二进制的 77E5 (unicode统一用两个字节byte即16位bit来表示所有字符)
    11100101 10111000 10000101 代入模版    
      E 5       B 8     8 5 

这就是将 U+77E5 按照 UTF-8 编码为字节序列 E79FA5 的过程。反之亦然。

unicod与utf-8

一个叫 ISO(国际标谁化组织)的国际组织决定着手解决各地区编码混乱的问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号 的编码!他们打算叫它”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode“。

unicode开始制订时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于ASCII里的那些“半角”字符,unicode包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于”半角”英文符号只需要用到低8位,所以其高8位永远是0,因此这种大气的方案在保存英文文本时会多浪费一倍的空间。

这时候,从旧社会里走过来的程序员开始发现一个奇怪的现象:他们的 strlen 函数靠不住了,一个汉字不再是相当于两个字符了,而是一个!是的,从unicode开始,无论是半角的英文字母,还是全角的汉字,它们都是统一的”一个字符“!同时,也都是统一的”两个字节“,请注意”字符”和”字节”两个术语的不同,“字节”是一个8位的物理存贮单元,而“字符”则是一个文化相关的符号。在unicode中,一个字符就是两个字节。一个汉字算两个英文字符的时代已经快过去了。

unicode同样也不完美,这里就有两个的问题,一个是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储空间来说是极大的浪费,文本文件的大小会因此大出二三倍,这是难以接受的。

unicode在很长一段时间内无法推广,直到互联网的出现,为解决unicode如何在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位。UTF-8就是在互联网上使用最广的一种unicode的实现方式,这是为传输而设计的编码,并使编码无国界,这样就可以显示全世界上所有文化的字符了。UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,当字符在ASCII码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分,注意的是unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节)。从unicode到utf-8并不是直接的对应,而是要过一些算法和规则来转换。

Unicode符号范围       |    UTF-8编码方式  
(十六进制 )           |   (二进制,1-4个字节,每个字节8位) 这里的二进制再用两位的16进制表示,见上面  
—————————————————————–   
0000 0000 - 0000 007F | 0xxxxxxx                  //这里007F刚好就是127,是ascII码包括的的所有字符
0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx  
0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx  
0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

base64编码

Base64 是网络上最常见的用于传输 8Bit 字节码的编码方式之一,Base64就是一种基于 64 个可打印字符来表示二进制数据的方法。Base64 编码是从二进制到字符的过程.

base64对照.jpg

普通字符串转 base64

首先清晰一个概念: 内存1个字节占8位即 1byte = 8bit;
Base64 要求把每三个8Bit 的字节转换为四个6Bit(为什么是 bBit呢,因为6位二进制最大 111111 等于 63,刚好 64 个字符) 的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个 8Bit 的字节,也就是说,转换后的字符串理论上将要比原来的长 1/3

转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,缓冲区中剩下的Bit0补足。如果最后剩下两个输入数据,在编码结果后加1=;如果最后剩下一个输入数据,编码结果后加2=;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

转码过程例子:
3*8=4*6
内存1个字节占8位
转前: s 1 3
先转成ascii:对应 115 49 51
2进制: 01110011 00110001 00110011
6个一组(4组) 011100110011000100110011
然后才有后面的 011100 110011 000100 110011
然后计算机是8位8位的存数 6不够,自动就补两个高位0了
所有有了 高位补0
科学计算器输入 00011100 00110011 00000100 00110011
得到 28 51 4 51
查对下照表 c z E z

转前: a
先转成ascii:           97(十进制,和用utf-8表示的16进制的 61是一样的)
2进制:                01100001
数据不足,补足(3*8)        01100001 00000000 00000000
6个一组(4组)        011000 010000 000000 000000
高位补0凑够8位        00011000 00010000 00000000 00000000
转十进制得到          24 16
查base64对照表              Y Q
最后补两个=得到            YQ==
如果最后剩下两个输入数据,在编码结果后加`1`个`=`;如果最后剩下一个输入数据,编码结果后加`2`个`=`

转前: 帅
先转成utf-8:           e5 b8 85      ##可通过let buf = Buffer.from("帅")获得utf-8编码,为16进制
2进制:                11100101 10111000 10000101
6个一组(4组)        111001 011011 100010 000101
高位补0凑够8位        00111001 00011011 00100010 00000101
转十进制得到          57 27 34 5
查base64对照表              5 b i F       ## 可通过buf.toString("base64")来验证

其他base64相关

url地址要先转码后再转base64.
点击查看base64的理解
转换方法;

!function(W){
  W.Base64 = {
     utf8ToBase64:function (str){
       return btoa(unescape(encodeURIComponent(str)));
     },
     base64ToUtf8: function(str){
        return decodeURIComponent(escape(atob(str)));
      }
  }
}(window);

相关文章

  • 搞定编码格式问题

    Unicode 于 utf-8 以下文章来自知乎回答 Unicode 是「字符集」UTF-8 是「编码规则」 其中...

  • java部署ubuntu后中文显示问号问题

    1、首先先回忆自身项目的编码格式,即在本地进行编码时使用的编码格式。UTF-82、检测tomcat的设置问题,在w...

  • org.xml.sax.SAXParseException; l

    问题 解决方法 原来文件是以UTF-8格式编码”,改成 “以UTF-8无BOM格式编码”。

  • 错误: 编码GBK的不可映射字符

    “javac 文件”时,报错编码GBK的不可映射字符,编码格式有问题,使用ANSI编码就可以了

  • Jira插件SynapseRT导入测试用例

    最近在研究插件SynapseRT管理测试用例 导入时遇到csv编码格式的问题 这个不同于tests插件,有编码格式...

  • [python]转换文件编码格式

    文件编码格式一直是很多人特别头疼的一件事情,最近由于跨平台开发,经常出现编码格式的问题。所以关于编码格式转换采用p...

  • unicode编码 转 中文

    方法一:格式化 方法二:先编码再解码 scrapy 爬虫返回json格式内容unicode编码转换为中文的问题解决

  • Windows下 Android studio terminal

    原因 编码格式问题,Android studio中是en_UTF8编码,而在Windows中是C_UTF8的编码格...

  • 插入数据库出现中文乱码问题

    插入数据库出现中文乱码问题 出现这种乱码问题,肯定是编码除了问题,编码和解码不是同一种编码格式就会出现乱码情况! ...

  • mysql表编码相关操作

    1、查看所有字段的编码格式: 2、查看表的编码格式: 3、修改数据库的编码格式: 4、修改表的编码格式 5、修改字...

网友评论

      本文标题:搞定编码格式问题

      本文链接:https://www.haomeiwen.com/subject/okjatctx.html