文章用JS简单的实现UTF-8编码和Base64编码,阅读本文可以了解Unicode 与 UTF-8 之间的转换,了解Base64编码为什么会使数据量变长。

概要:

  • Unicode简单了解
  • UTF-8编码
  • Base64编码
  • 总结

Unicode,ASCII,GB2312编码集合等,类似于字典。字符的编码,类似于字典中的字在哪一页哪一行。当不同系统用同一本字典查同一个编码得到的字符会一致。

如下图:

1. Unicode简单了解

wikipedia:

Unicode is a computing industry standard for the consistent encoding, representation, and handling of text expressed in most of the world's writing systems.

在创造Unicode之前各种语言有不同的编码集合,ASCII,GB2312等也是发展过程中编码集合,而且这些编码集合相互冲突,给不同语言系统进行交流带来了麻烦。因为两种相同的字符在不同的编码系统中可能有完全不同的意思。于是Unicode出现了,Unicode编码集合给每个字符提供了一个唯一的数字,不论平台,程序,语言,Unicode 字符集因此被广泛应用。

Javascript程序是用Unicode字符集编写的, 字符串(string)中每个字符通常来自于Unicode 字符集。

Unicode 字符集类似于字典,字符就类似于字。字符的Unicode码值,就类似于字在字典的第页第几行。

2. utf8编码

2.1为何有了Unicode字符集还需要 一个编码来传输了?

因为Unicode 编码转换成二进制,是一串0,和1,传输个另一方的时候,需要一个规则来分割这一串0、1。

于是就出现了UTF-n 编码们。

8bit = 1byte

资料

UTF(Universal Transformation Format,通用传输格式),其实就是不改变字符集中各个字符的代码,建立一套新的编码方式,把字符的代码通过这个编码方式映射成传输时的编码,最主要的任务就是在使用Unicode字符集保持通用性的同时节约流量和硬盘空间。

存储
Unicode是一个符号集,规定了符号的二进制代码,没有规定这个二进制代码应该如何存储(即占用多少个字节)所以出现了不同的存储实现方式。
UTF-32

字符用四个字节表示

UTF-16

字符用两个字节或四个字节表示

UTF-8

一种变长的编码方式,根据需要用1~4个字节来表示字符,(按需传递节约流量和硬盘空间,因此UTF-8用的比较广)

2.2UTF-8编码规则

  • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。
  • 对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n+ 1位设为0,后面字节的前两位设为10。剩下,全部为这个符号的 Unicode 编码。
Unicode符号范围 |  Unicode符号范围     |        UTF-8编码方式
(十进制) | (十六进制) | (二进制)
---------------+----------------------+---------------------------------------------
0 ~ 127 | 0000 0000-0000 007F | 0xxxxxxx
128 ~ 2047 | 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
2048 ~ 65535 | 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
65536 ~1114111 | 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

eg: 字符罗的UTF-8编码

用codePointAt得到了字符的Unicode 编码,确认用几个字节表示,然后按照规则填充。

编码流程:

资料补充:

ES6 提供了codePointAt()方法,能够正确处理字节储存的字符,返回一个字符的码点(Unicode 编码)。

ES6 提供了String.fromCodePoint()方法能正确处理一个码点(Unicode 编码),返回码点(Unicode 编码)对应的字符

2.3UTF-8编码解码简单实现

 function encodeUtf8(str) {
var bytes = []
for (ch of str) {
// for...of循环,能正确识别 32 位的 UTF-16 字符, 可以查阅资料了解。
let code = ch.codePointAt(0)
if (code >= 65536 && code <= 1114111) {// 位运算, 补齐8位
bytes.push((code >> 18) | 0xf0)
bytes.push(((code >> 12) & 0x3f) | 0x80)
bytes.push(((code >> 6) & 0x3f) | 0x80)
bytes.push((code & 0x3f) | 0x80)
} else if (code >= 2048 && code <= 65535) {
bytes.push((code >> 12) | 0xe0)
bytes.push(((code >> 6) & 0x3f) | 0x80)
bytes.push((code & 0x3f) | 0x80)
} else if (code >= 128 && code <= 2047) {
bytes.push((code >> 6) | 0xc0)
bytes.push((code & 0x3f) | 0x80)
} else {
bytes.push(code)
}
}
return bytes
}
function padStart(str, len, prefix) {
return ((new Array(len + 1).join(prefix)) + str).slice(-len) // 也可用 new Array(len+1).fill(0)
}
function decodeUtf8(str) {
let strValue = ''
let obStr = [...str].map((ch)=> {
return padStart(parseInt(ch,16).toString(2), 4, 0)
}).join('').match(/\d{8}/g).map((item)=> parseInt(item,2))
for (var i = 0; i < obStr.length; ) { let code = obStr[i]
let code1, code2, code3, code4, hex
if ((code & 240) == 240) {
code1 = (code & 0x03).toString(2)
code2 = padStart((obStr[i + 1] & 0x3f).toString(2),6, '0')
code3 = padStart((obStr[i + 2] & 0x3f).toString(2),6, '0')
code4 = padStart((obStr[i + 3] & 0x3f).toString(2),6, '0')
hex = parseInt((code1 + code2 + code3 + code4),2)
strValue = strValue + String.fromCodePoint(hex)
i = i + 4
} else if ((code & 224) == 224) {
code1 = (code & 0x07).toString(2)
code2 = padStart((obStr[i + 1] & 0x3f).toString(2),6, '0')
code3 = padStart((obStr[i + 2]& 0x3f).toString(2),6, '0')
hex = parseInt((code1 + code2 + code3),2)
strValue = strValue + String.fromCodePoint(hex)
i = i + 3
} else if ((code & 192) == 192) {
code1 = (code & 0x0f).toString(2)
code2 = padStart((obStr[i + 1] & 0x3f).toString(2),6, '0')
hex = parseInt((obStr + code2),2)
strValue = strValue + String.fromCodePoint(hex)
i = i + 2
} else {
hex = code
strValue = strValue + String.fromCodePoint(code)
i = i + 1
}
}
return strValue
}
function transferHex(bytes) {
let s = ''
bytes &&
bytes.forEach(ch => {
s = s + ch.toString(16)
})
return s
}
let text = "罗小步 啊哈哈

Unicode字符集,utf8编码,base64编码简单了解的更多相关文章

  1. 【转】字符编码笔记:ASCII、Unicode、UTF-8 和 Base64

    1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态(-128~127),这被称为一 ...

  2. 字符编码笔记:ASCII、Unicode、UTF-8 和 Base64

    1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态(-128~127),这被称为一 ...

  3. Unicode 字符集与它的编码方式

    正式内容開始之前,我们先来了解一个基本概念,编码字符集. 编码字符集:编码字符集是一个字符集,它为每个字符分配一个唯一数字.Unicode 标准的核心是一个编码字符集,字母"A"的 ...

  4. Qt实现16进制unicode转utf-8以及国际音标编码问题

    由于项目需要,需要对网络资源进行解码.遇到编码问题.研究了下基本编码原理.于是有了下面两个通用代码 1. 16进制unicode转换为utf-8中文显示 QString unicodeToUtf_8( ...

  5. ASCII、Unicode、UTF-8以及Python3编码问题

    编码问题,其实的确是个很烦人的问题,一开始觉得不需要看,到后来出现问题,真的是抓狂, 而像我们这些刚刚涉及到这些问题的小白来说,更是无从下手,所以查阅资料,总结理解下各个概念以及Python3的编码问 ...

  6. ASCII、Unicode、UTF-8 字符串和编码

    字符编码 我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特 ...

  7. 【字符编码】字符编码 && Base64编码算法

    一.前言 在前面的解决乱码的一文中,只找到了解决办法,但是没有为什么,说白了,就是对编码还是不是太熟悉,编码问题是一个很简单的问题,计算机从业人员应该也必须弄清楚,基于编码的应用有Base64加密算法 ...

  8. 001_从原理上搞定编码-- Base64编码

    开发者对 Base64编码肯定很熟悉,是否对它有很清晰的认识就不一定了.实际 上Base64已经简单到不能再简单了,如果对它的理解还是模棱两可实在不应该.大概介绍一下Base64的相关内容,花几分钟时 ...

  9. 从原理上搞定编码-- Base64编码

    BASE64是一种编码方式,通常用于把二进制数据编码为可写的字符形式的数据.这是一种可逆的编码方式.编码后的数据是一个字符串,其中包含的字符为:A-Z.a-z.0-9.+./共64个字符:26 + 2 ...

  10. python 应用 base64、hmac、hashlib包实现:MD5编码 base64编码解码、SHA256编码、urlsafe_b64encode编码等等基本所有的加密签名的方法

    用python做HTTP接口自动化测试的时候,接口的很多参数是经过各种编码加密处理后在传到后台的,这里列举出python实现 应用 base64.hmac.hashlib包实现:md5编码 sha1编 ...

随机推荐

  1. CyclicBarrier源码阅读

    一种允许多个线程全部等待彼此都到达某个屏障的同步机制 使用 多个线程并发执行同一个CyclicBarrier实例的await方法时,每个线程执行这个方法后,都会被暂停,只有当最后一个线程执行完awai ...

  2. git 指定自己的sshkey

    在服务器上生成ssh-key以后,需要把公钥放在github上,但是,这个公钥只能放在一个账户里,如果放在第二个账户里,就会提示这个key已经被用了,这是前提 一个可能的场景是这样的: 你们公司有好几 ...

  3. idea 更新后和新的直接安装前,都需要配置 idea64.exe.vmoptions 后再使用

    配置合适的参数提升性能,默认的性能不高

  4. Golang协程实现流量统计系统(1)

    # 学习内容: # 学习目标: 学习Golang的基础开发 常用的Golang编程技艺 精巧省力的Go Lib 协程的真实应用实践 与其他语言对比着学 协程并发模型的深度应用 Growth hacki ...

  5. CopyOnWriteArrayList使用

    1.在遍历操作数量大大超过可变操作是(add,set等等)使用.原因是其可变操作是通过对底层数据进行一次新的复制来实现的. 2.迭代器创建后,其不会反应列表的添加.移除或更改.其迭代器是”快照“风格的 ...

  6. 清明 DAY 4

    ~~~~~zhx并没有讲完~~~~~~QAQ~~~~~~ (其实并没有更完)

  7. Android Studio在Make Project时下载Grandle特别慢

    SDK下载完成了,建个工程, 又蒙了: Server returned HTTP response code: 502 for URL: https://services.gradle.org/dis ...

  8. leetcode 188. 买卖股票的最佳时机 IV

    参见 本题采用了第一列初始化后,从左侧向右开始递推的方式,但从上往下递推应该也成立,以后尝试一下 想写一个普适性的适用于n天交易k次持有j股的状态方程但是有问题:对于交易次数过多的情况数组会超出界限: ...

  9. Anaconda 32在windows下安装gensim

    安装Anaconda 2.4以后运行corpora.MmCorpus.serialize的时候出错 换了Anaconda 2.1以后没问题了 原因:Anaconda 2.4的numpy是1.10.1版 ...

  10. 【7】解决:移动端点击a链接出现蓝色边框

    [1]_blank : 浏览器总在一个新打开.未命名的窗口中载入目标文档. [2]title :  鼠标悬浮显示的文字. [3]href : 跳转到哪个链接.     a{    border: no ...