浅谈一下前端字符编码

背景

众所周知,计算机只能识别二进制,它是由逻辑电路组成,逻辑电路通常只有两个状态,开关的接通与断开,这两种状态正好可以用二进制数的0和1表示。但是现实中存在着其他的字符:数字、字母、中文、特殊符号等。因此就需要将这些字符转化成计算器可以识别的二进制编码。而我们在开发过程中,也常常会遇到各种各样的编码,例如ACSII、utf-8、base64等编码,接下来让我们来看一下这些常见编码。
编码方式

ASCII

我们知道在计算机存储数据时要使用二进制进行表示。而最初计算机只在美国使用,因此人们要考虑如何使用二进制来表达 52 个英文字母(包括大小写)、阿拉伯数字(0-9)以及常用的符号(如! @ # $ 等)。
于是便有从电报码发展而来的 ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)(发音 /ˈæski/)编码。它定义了英文字符和二进制的对应关系,一直沿用至今。

标准的ASCII字符总计有128个字符(2^7),字节的最高位一般设置为0。按照字符是否可见,可分为33个不可见字符,95个可见字符。

● 不可见字符:0-31 和 127 (0x00-0x1F 和 0x7F) 为不可见字符,也是控制字符,共 33 个。用于进行终端的换行、响铃、删除等动作。
在这里插入图片描述

● 可见字符:32-126 (0x20-0x7E) 为可见字符,共 95 个,存储了空格、0-9 十个阿拉伯数字、52 个大小写英文字母,以及标点、运算符号等。
在这里插入图片描述

虽然现代英语使用 128 个字符就足够了,但表示其他语言就远远不够了。因此当 ASCII 进入欧洲后,又被扩展为了 EASCII(Extended ASCII),将 7 bit 扩展为 8 bit,从128为扩展成256位,并且前 127 个编码含义和ASCII 保持一致。
编码
我们要知道一个字符对应的二进制,可以先找到它对应的十进制,然后再转化为二进制。
例如‘d’字符,它对应的十进制是100,转二进制的口诀是:除2倒取余法”,即将十进制整数除以2,得到一个商和一个余数;再将商除以2,又得到一个商和一个余数;以此类推,直到商等于零为止。
计算如下,倒取余数可以得到:110 0100
在这里插入图片描述

解码
可以看到以下的编码,使用 ASCII 码进行映射时,下面的二进制编码可以翻译成“Hello world”。

01001000 01100101 01101100 01101100 01101111 00100000 01110111 
01101111 01110010 01101100 01100100

我们列举一下第一个二进制的0100100的转化,对应十进制的转法是:把二进制数按权展开、相加即得十进制数。

2^6+2^3=64+8=72

可以算出它对应的十进制是72,从表格上对应到的字符就是H。

ASCII的主要缺点是它只能表示256个不同的字符,因为它只有8位。这意味着ASCII无法编码世界上许多其他语言中的字符。如果想要在计算机上使用中文、俄语、日语等语言,就需要另一种不同的字符编码标准。Unicode进一步扩展为UTF-8、UTF-16、UTF-32等编码方案,以便能够编码各种类型的字符。因此,ASCII和Unicode之间的主要区别在于所使用的位数进行编码。接下来我们来看一下Unicode的概念和使用方式。

Unicode

统一码(Unicode),也叫万国码、单一码它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、垮平台进行文本转换、处理的要求,是国际组织制定的,用于收纳世界上所有文字和符号的字符集方案。前128个字符同ASCII一样,进行扩充后,使用数字0-0x10FFFF来映射这些字符。

● 码点
Unicode 规定了每个字符的数字编号,这个编号被称为 码点(code point)。码点以 U+hex 的形式表示,U+是代表Unicode的前缀,而 hex 是一个16进制数。取值范围是从 U+0000 到 U+10FFFF。每个码点对应一个字符,绝大部分的常见字符在最前面的 65536 (2^16)个字符,范围是 U+0000到U+FFFF。

● 字符平面:目前的Unicode分成了17个编组,也称平面,每个平面有65536个码点。
○ 基本平面:U+0000 - U+FFFF,多数常见字符都在该区间,其他平面则为辅助平面。
○ 辅助平面:U+10000 到 U+10FFFF,如我们在网上常见 Emoji 表情。

Unicode通常为两个字节,对于英文字符的一个字节即可表示,高位字节补0,这样对比ASCII编码存储空间就会翻倍,在存储和传输上就十分不划算。这就会使得Unicode编码一时间很难推广。于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16、UTF-32 应运而生(UTF-8是8位的单字节码元,UTF-16是16位的双字节码元,UTF-32是32位的四字节码元)。UTF是Unicode TransferFormat的缩写。
Unicode和ASCII的区别如下:

UTF-8

UTF-8是一种可变长度字符编码,其第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部分修改后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。

计算机在读取 UTF-8 中以 0 开头的内容时,就知道只需要读取一个字节并显示 Unicode 中 0-127 范围内的正确字符即可。如果遇到两个 1,就需要读取 2 个字节,范围为128-2047,3 个 1 在一起表示需要读取三个字节。

十六进制二进制范围
0000 0000 - 0000 007F0xxxxxxx0-127
0000 0080 - 0000 07FF110xxxxx 10xxxxxx128-2047
0000 0800 - 0000 FFFF1110xxxx 10xxxxxx 10xxxxxx2048-65535
0001 0000 - 0010 FFFF1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx65536-2098151

应用

1. URL编码
在前端常接触的网页中,URL链接编码也是非常常见的。因为URL 只能包含标准的 ASCII 字符,所以必须对其他特殊字符进行编码。
JavaScript提供了四个URL的编码/解码方法,可以用于将非ASCII码的字符,如中文字符、特殊字符、表情字符等,进行UTF-8的编解码操作:
● 编码:encodeURI() 和 encodeURIComponent()
● 解码:decodeURI() 和 decodeURIComponent()

转换方式为:先转为UTF-8的字节码,然后前面加个 % 进行拼接得到编码结果。

encodeURI(' 12 33')--->'%2012%2033'
decodeURI('%2012%2033')--->' 12 33'

注意encodeURL有11个字符不能进行编码,只能使用encodeURLComponent进行编码

encodeURI与encodeURIComponent区别

○ encodeURI
encodeURI通常用于转码整个 URL,不会对URL 元字符以及语义字符进行转码,URL元字符:

  1. URL 元字符:分号(;),逗号(,),斜杠(/),问号(?),冒号(:),at(@),&,等号(=),加号(+),美元符号($),井号(#)
  2. 语义字符:a-z,A-Z,0-9,连词号(-),下划线(_),点(.),感叹号(!),波浪线(~),星号(*),单引号('),圆括号(())

○ encodeURIComponent
encodeURIComponent()通常只用于转码URL组成部分,如URL中?后的一串;会转码除了语义字符之外的所有字符,即元字符也会被转码

2. 指定编码
如果没有显式指定编码方式,浏览器假定任何程序的源代码都是用本地字符集编写的,这会因国家/地区而异,可能会出现意料之外的情况。因此,给 JavaScript 文档设置字符集非常重要,可以使用以下三种方式进行设定

○ 获取文件时,可以在Content-type指定

Content-Type: application/javascript; charset=utf-8

○ 在script标签设置charset

<script src="./app.js" charset="utf-8">

○ 嵌入head中


<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8">
</head>

在前端开发中,Javascript程序是使用Unicode字符集,Javascript源码文本通常是基于UTF-8编码。
但js代码中的字符串类型是UTF-16编码的,正如 ECMAScript 标准所说,JavaScript 字符串都是 UTF-16 序列。这也是解释了api接口返回字符串在前端出现乱码,因为多数服务都使用utf-8编码,前后编码方式不一致。

3. ‘锟斤拷’乱码问题
由于 Unicode 字符集在不断更新中,因此会出现 A 系统发送的字符,在 B 系统中无法识别的情况。于是 Unicode 规定对于无法识别的字符,一律使用 �(0xFFFD )字符来代替。
将FFFD转utf-8时,我们可以先将其转十进制等于65534,发现其在三个字节内的,因此先将其转成二进制。
从低位开始分成六位一组得到三组: 1111 111111 111110。后两组前面补10,第一组补1110。最后得到utf-8编码: 11101111 10111111 10111110。

//十六进制 -》十进制
FFFD -> 15*16^3+15*16^2+15*16+14=65534  -1111 111111 11111011101111 10111111 10111110EF        BF       BD

然后再将其转成十六得到EF BF BD,即 0xFFFD 在 UTF-8 编码下为 0xEF 0xBF 0xBD,当多 � 出现时,就会产生连续的 0xEF 0xBF 0xBD 0xEF 0xBF 0xBD。
如果这些字符又被使用了 GB 编码的程序中打开,就会按照 GB 双字节编码将其解析。这样刚好就对应了 「0xEFBF 锟」 ,「0xBDEF 斤」,「0xBFBD 拷」 这几个字。
在这里插入图片描述

base64

Base64 也称为 Base64 内容传输编码。Base64 是将二进制数据编码为 ASCII 文本。Base64 一个字节只能表示 64 种情况,且编码格式每个字节的前两位都只能是 0,使用剩下的 6 位表示内容。再加上大多数字符集中存在的一个填充字符=。所以它是一种仅使用可打印字符表示二进制数据的方法。Base64 常用于在通常处理文本数据的场景,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据、以及图片地址。

这种编码格式无法充分利用存储资源,效能较低。那为什么还会成为网络中的普遍用法呢?
----其实 Base64 最早是应用在邮件传输协议中的。当时邮件传输协议只支持 ASCII 字符传递,使用 ASCII 码来表示所有的英文字符和数字还有一些符号。这里有一个问题,如果邮件中只传输英文数字等,那么 ASCII 可以直接支持。但是如果要在文件中传输图片、视频等资源的话,这些资源转成 ASCII 的时候会出现非英文数字的情况。而且邮件中还存在很多控制字符,这些控制字符又会成为不可见字符。非英文字符和控制字符在传输过程中很容易产生错误,影响邮件的正确传输。为此才有了诞生了一个新的编码规则,把二进制以 3 个字节为一组,再把每组的 3 个字节(24 位)转换成 4 个 6 位,每 6 位根据查以下映射表对应一个 ASCII 符号。不够6位使用000000 字节值在末尾补足,使其字节数能够被 3 整除,补位用 = 表示,每2个额外的0由1个 = 字符表示,并在解码时自动去除这就是 Base64。
在这里插入图片描述

编码
例如我们要编译hello,首先将其转成ASCII码01001000 01100101 01101100 01101100 01101111
Hello–> 01001000 01100101 01101100 01101100 01101111
然后将其从前往后,三个字节为一组,后面两个字节也自成一组。每一组按照六位为一组,不够六位补0。
算出每组对应的十进制,然后到表格中找出对应的符号,对应的转化如下,由于最后的一组补充了两个0,因此需要补充1个填充字符=

010010 000110 010101 101100           011011 000110 111100
18       6      21      44              27    6      60
S        G       V       s               b     G     8=

即编码后hello-》SGVsbG8=

解码
了解了编码,我们来看一下解码,还是用上面的例如对于编码后的字符SGVsbk8==。
四个字符为一组,并且删除每一组尾部的=。将每一个字符对应的十进制找到,然后再转化为二进制。从高到低每8位为一组,可得到:01001000 01100101 01101100 01101100 01101111对应ASCII表格对应的字符即可得到Hello

S        G         V        s                        b          k        8
18       6         21       44                       27         10       60
010010   000110   010101   101100                    011011    000110   111100
01001000  01100101  01101100                         01101100 01101111

应用

● javascript对应的base64编解码方法
在JavaScript 中,可以使用 btoa(binary to ASCII)和 atob(ASCII to binary)方法来做 Base64 的编码和解码。
例如对‘Hello’做 Base64 的编码与解码:
在这里插入图片描述
对于中文的base64编解码,由于ASCII 无法表示中文,因此要先做 UTF-8 编码,然后再做Base64 编码;解码方式为先做 Base64 解码,再做UTF-8 解码:

const encodedData = btoa(encodeURI('你好')); //  "JUU0JUJEJUEwJUU1JUE1JUJE"
const decodedData = decodeURI(atob(encodedData)); // "你好"

在这里插入图片描述

● base64图片地址
通常在图片比较多的情况为了减少http请求,图片地址我们会用base64编码。
前端拿到这个data字符串后,先拼接一下前缀:data:图片类型 ; 编码类型, data字符串数据
data:image/png;base64,iVBORw0KGgoAA…

有两种方式显示图片

  1. css方式-背景图片
img {background-image: url(data:image/png;base64,iVBORw0KG......);
}    
  1. img标签方式
<img width="900" height="450" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGMAAAAqCAYAAA...."/>

参考资料

● 聊聊前端字符编码:ASCII、Unicode、Base64、UTF-8、UTF-16、UTF-32-51CTO.COM
● Base64 编码知识,一文打尽!
● 关于编码的那些事——前端应该了解的字符编码_winty~~的博客-CSDN博客
● 前端开发中需要搞懂的字符编码知识_前端的字符和字节_jh035的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习记忆——数学篇——顺口溜记忆法+谐音记忆法+其他

顺口溜记忆法 【训练】 一次绝对不等式的解集&#xff1a;不等式| x x x| &#xff1e; a ( a > 0 ) &#xff1e;a(a>0) &#xff1e;a(a>0)的解集是 X > a 或 X < − a X>a或X<-a X>a或X<−a&#xff0c;不等式| x x x| < a ( a > 0 ) <…

Java————数组

1 、数组 数组可以看成是相同类型元素的一个集合&#xff0c; 在内存中是一段连续的空间。 每个空间有自己的编号&#xff0c;其实位置的编号为0&#xff0c;即数组的下标。 数组是引用类型。 1. 数组的创建 T[] 数组名 new T[N];T&#xff1a;表示数组中存放元素的类型 …

苹果官网数秒就被抢购引发崩溃,iPhone15热销,对小丑的强烈讽刺

面对网络上对iPhone15恶评如潮&#xff0c;甚至还有假5G等的风波&#xff0c;然而iPhone15的预购却超乎寻常的热烈&#xff0c;以至于苹果官网在开售几秒内就已崩溃了&#xff0c;显示出今年的iPhone15销售情况恐怕比往年的更要好。 除了苹果官网被抢购到崩溃之外&#xff0c;几…

Spring + vue 项目部署(全网最详细教程_含内网穿透部署)

本项目以Springboot 2.7.11和vue2做参考示例 第一步 展示前后端代码的成品 前端Vue 后端Java 项目写完后&#xff0c;差不多就是这个样子&#xff0c;仅供参考&#xff01; 第二步 开始打包前后端项目 前端打包的方式有以下几种&#xff1a; 方法1: #直接打包&#xff0…

Hugging Face使用Stable diffusion Diffusers Transformers Accelerate Pipelines

Diffusers A library that offers an implementation of various diffusion models, including text-to-image models. 提供不同扩散模型的实现的库&#xff0c;代码上最简洁&#xff0c;国内的问题是 huggingface 需要翻墙。 Transformers A Hugging Face library that pr…

【视觉SLAM入门】8 回环检测,词袋模型,字典,感知,召回,机器学习

"见人细过 掩匿盖覆” 1. 意义2. 做法2.1 词袋模型和字典2.1.2 感知偏差和感知变异2.1.2 词袋2.1.3 字典 2.2 匹配(相似度)计算 3. 提升 前言&#xff1a; 前端提取数据&#xff0c;后端优化数据&#xff0c;但误差会累计&#xff0c;需要回环检测构建全局一致的地图&…

深度学习编译器关键组件

1 高层中间代码 为了克服传统编译器中采用的IR限制DL模型中复杂计算的表达的局限性&#xff0c;现有的DL编译器利用高层IR&#xff08;称为图IR&#xff09;进行高效的代码优化设计。 1.1 图表示 基于DAG的IR&#xff1a;基于DAG的IR是编译器构建计算图的最传统方法之一&…

[NLP] LLM---<训练中文LLama2(四)方式一>对LLama2进行SFT微调

指令精调 指令精调阶段的任务形式基本与Stanford Alpaca相同。训练方案也采用了LoRA进行高效精调&#xff0c;并进一步增加了可训练参数数量。在prompt设计上&#xff0c;精调以及预测时采用的都是原版Stanford Alpaca不带input的模版。对于包含input字段的数据&#xff0c;采…

排序算法:计数排序

前文说到&#xff0c;19591959 年 77 月&#xff0c;希尔排序通过交换非相邻元素&#xff0c;打破了O(n^2)的魔咒&#xff0c;使得排序算法的时间复杂度降到了O(nlogn) 级&#xff0c;此后的快速排序、堆排序都是基于这样的思想&#xff0c;所以他们的时间复杂度都是 O(nlogn)。…

6.2.3 【MySQL】InnoDB的B+树索引的注意事项

6.2.3.1 根页面万年不动窝 B 树的形成过程是这样的&#xff1a; 每当为某个表创建一个 B 树索引&#xff08;聚簇索引不是人为创建的&#xff0c;默认就有&#xff09;的时候&#xff0c;都会为这个索引创建一个 根节点 页面。最开始表中没有数据的时候&#xff0c;每个 B 树…

动手学深度学习——Windows下的环境安装流程(一步一步安装,图文并配)

目录 环境安装官网步骤图文版安装Miniconda下载包含本书全部代码的压缩包使用conda创建虚拟&#xff08;运行&#xff09;环境使用conda创建虚拟环境并安装本书需要的软件激活之前创建的环境打开Jupyter记事本 环境安装 文章参考来源&#xff1a;http://t.csdn.cn/tu8V8 官网…

使用Spring Security保障你的Web应用安全

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Vim的基础操作

前言 本文将向您介绍关于vim的基础操作 基础操作 在讲配置之前&#xff0c;我们可以新建一个文件 .vimrc&#xff0c;并用vim打开在里面输入set nu 先给界面加上行数&#xff0c;然后shift &#xff1b;输入wq退出 默认打开&#xff1a;命令模式 在命令模式中&#xff1a…

MySQL阅读网上MySQL文章有感的杂记

前言&#xff0c;本篇文章将会记录各大MySQL文章的一些有意思的内容摘取&#xff0c;以及一些问题的提问&#xff0c;并且持续更新。 并且MySQL专栏将会记录MySQL常考的场景题等实战。 问题归类&#xff1a; 1.MySQL从加锁范围上分为哪三类? 2.全局锁加锁方法的执行命令是什么…

【配电变电站的最佳位置和容量】基于遗传算法的最优配电变电站放置(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

数据结构之美:如何优化内存和性能

文章目录 什么是数据结构&#xff1f;内存优化使用紧凑的数据类型避免冗余存储使用位运算压缩数据 性能优化使用适当的数据结构减少不必要的复制使用合适的算法 数据结构优化的案例分析结论 &#x1f389;欢迎来到数据结构学习专栏~探索数据结构之美&#xff1a;如何优化内存和…

Fiddler抓http数据

目录 参考博客 一、Fiddler配置二、分析Http请求1. Http消息结构简介1.1 Request请求消息1.2 Response响应消息 2. 分析Get接口2.1 请求示例2.2 查看Get请求2.3 查看Get响应 3 分析Post接口 参考博客 一、Fiddler配置 首先需要对Fiddler抓取Https请求进行相关配置&#xff1a…

11-集合和学生管理系统

1.ArrayList 集合和数组的优势对比&#xff1a; 长度可变添加数据的时候不需要考虑索引&#xff0c;默认将数据添加到末尾 1.1 ArrayList类概述 什么是集合 ​ 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以发生改变 ArrayList集合的特点 ​ 长度可以变化…

计算机视觉面试题整理

1、介绍目标检测网络yolo系列以及ssd系列的原理&#xff0c;yolo对小目标检测不好的原因&#xff0c;除了缩小anchor外还可以如何改善&#xff1f; Yolo目标检测&#xff1a;YOLO是一种实时目标检测算法&#xff0c;其核心思想是将目标检测问题归为一个回归问题&#xff0c;直…

git clone报错Failed to connect to github.com port 443 after 21055 ms:

git 设置代理端口号 git config --global http.proxy http://127.0.0.1:10085 和 git config --global https.proxy http://127.0.0.1:10085 然后就可以成功git clone hugging face的数据集了 如果是https://huggingface.co/datasets/shibing624/medical/tree/main 那么…