关于Unicode,UTF-8,GB编码详解

2023-11-08

内容来自网络, 有部分修正

一、首先我们需要明白关于字符(character),字符集(character set),字符编码方式(character encoding)的概念。

  1. 字符 :字符是抽象的最小文本单位。它没有固定的形状(可能是一个字形),而且没有值。“A”是一个字符,“€”(德国、法国和许多其他欧洲国家通用货币的标志)也是一个字符。“中”“国”这是两个汉字字符。字符仅仅代表一个符号。

  2. 字符集 :也就是某个符号和某个数字映射关系的一个表,也就是它决定了107 是koubei 的 ‘k’,21475 是口碑的“口”,不同的表有不同的映射关系,如 ascii,gb2312,Unicode(注意UTF-8不是字符集). 通过这个数字和字符的映射表,我们可以把一个二进制表示的数字转换成某个字符。

  3. 字符编码方式 :例如,同是对于应“口”的 21475 这个数,我们是用 \u5k3e3 表示呢,还是用 %E5%8F%A3 来表示呢?这就是由 character encoding 来决定的。UTF-8指的也就是字符的编码方式了。

二、关于ASCII, GB2312/GBK ,以及Unicode

一直对字符的各种编码方式懵懵懂懂,什么ANSI、UNICODE、UTF-8、GB2312、GBK、DBCS、UCS……是不是看的很晕,假如您细细的阅读本文你一定可以清晰的理解他们。

1. ASCII码

很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物。他们看到8个开关状态是好的,于是他们把这称为 字节

再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出很多状态,状态开始变来变去。他们看到这样是好的,于是它们就把这机器称为 计算机

开始计算机只在美国用。八位的字节一共可以组合出256(2的8次方)种不同的状态。

他们把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端、打印机遇上约定好的这些字节被传过来时,就要做一些约定的动作。遇上00x10, 终端就换行,遇上0x07, 终端就向人们嘟嘟叫,例如遇上0x1b, 打印机就打印反白的字,或者终端就用彩色显示字母。他们看到这样很好,于是就把这些0x20以下的字节状态称为" 控制码 "。

他们又把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机就可以用不同字节来存储英语的文字了。大家看到这样,都感觉很好,于是大家都把这个方案叫做ANSI 的" Ascii "编码(American Standard Code for Information Interchange, 美国信息互换标准代码 )。当时世界上所有的计算机都用同样的ASCII方案来保存英文文字。

后来,就像建造巴比伦塔一样,世界各地的都开始使用计算机,但是很多国家用的不是英文,他们的字母里有许多是ASCII里没有的,为了可以在计算机保存他们的文字,他们决定采用127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128到255这一页的字符集被称" 扩展字符集 "。从此之后,贪婪的人类再没有新的状态可以用了,美国可能没有想到还有第三世界国家的人们也希望可以用到计算机吧!

2. GB2312/GBK

等中国人们得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存呢。但是这难不倒智慧的中国人民,我们不客气地把那些127号之后的奇异符号们直接取消掉,GB其实就是国标拼音的头字母。

规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的" 全角 "字符,而原来在127号以下的那些就叫" 半角 "字符了。

中国人民看到这样很不错,于是就把这种汉字方案叫做 GB2312 (2312是版本号, 全称是GB2312-1980)。GB2312 是对 ASCII 的中文扩展。

但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来,特别是某些很会麻烦别人的国家领导人。于是我们不得不继续把 GB2312 没有用到的码位找出来老实不客气地用上。

后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准,GBK 包括了 GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。

后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK 扩成了 GB18030 。从此之后,中华民族的文化就可以在计算机时代中传承了。

中国的程序员们看到这一系列汉字编码的标准是好的,于是通称他们叫做" DBCS "(Double Byte Charecter Set, 双字节字符集 )。在DBCS系列标准里,最大的特点是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,因此他们写的程序为了支持中文处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,那么就认为一个双字节字符集里的字符出现了。那时候凡是会编程的计算机僧侣们都要每天念下面这个咒语数百遍:

"一个汉字算两个英文字符!一个汉字算两个英文字符……"

3. Unicode

因为当时各个国家都像中国这样搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码,连大陆和台湾这样只相隔了150海里,使用着同一种语言的兄弟地区,也分别采用了不同的 DBCS 编码方案——当时的中国人想让电脑显示汉字,就必须装上一个"汉字系统",专门用来处理汉字的显示、输入的问题,但是那个台湾的愚昧封建人士写的算命程序就必须加装另一套支持BIG5 编码的什么"倚天汉字系统"才可以用,装错了字符系统,显示就会乱了套!这怎么办?而且世界民族之林中还有那些一时用不上电脑的穷苦人民,他们的文字又怎么办?

真是计算机的巴比伦塔命题啊!

正在这时,大天使加百列及时出现了——一个叫 ISO (国际标谁化组织)的国际组织决定着手解决这个问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码!他们打算叫它"Universal Multiple-Octet Coded Character Set",简称 UCS, 俗称 " UNICODE "。

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

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

从前多种字符集存在时,那些做多语言软件的公司遇上过很大麻烦,他们为了在不同的国家销售同一套软件,就不得不在区域化软件时也加上那个双字节字符集咒语,不仅要处处小心不要搞错,还要把软件中的文字在不同的字符集中转来转去。UNICODE 对于他们来说是一个很好的一揽子解决方案,于是从Windows NT 开始,MS 趁机把它们的操作系统改了一遍,把所有的核心代码都改成了用UNICODE 方式工作的版本,从这时开始,WINDOWS 系统终于无需要加装各种本土语言系统,就可以显示全世界上所有文化的字符了。

但是,UNICODE 在制订时没有考虑与任何一种现有的编码方案保持兼容,这使得 GBK 与UNICODE 在汉字的内码编排上完全是不一样的,没有一种简单的算术方法可以把文本内容从UNICODE编码和另一种编码进行转换,这种转换必须通过查表来进行。

如前所述,UNICODE 是用 两个字节 来表示为一个字符(称为 UCS-2 ),他总共可以组合出65535不同的字符,这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系,ISO已经准备了 UCS-4 ( 四个字节 )方案,说简单了就是四个字节来表示一个字符,这样我们就可以组合出21亿个不同的字符出来(最高位有其他用途),这大概可以用到银河联邦成立那一天吧!

unicode可以是两个字节或是4个字节。目前的用于实用的Unicode版本对应于UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。unicode使用4字节的,叫UCS-4。

三、编码问题

到目前为止,上述的讲的都是字符集。 UCS(Unicode Character Set) 还仅仅是字符对应码位的一张表而已,比如"汉"这个字的码位是6C49。字符具体如何 传输和储存 则是由 UTF ( UCS Transformation Format ) 来负责。同时,Unicode(UCS)只是规定如何编码,并没有规定如何传输,保存这个编码。例如“汉”字的UCS编码是6C49,我可以用4个ASCII数字来传输和保存这个编码,也可以用UTF-8编码方式来储存,接下来我们来谈谈UTF-8。

UTF8 并不算是一种电脑编码,而 是一种储存和传送的格式 ,如前所述,每个Unicode/UCS字符都以 2或4个bytes来储存,看看以下的比较:

以"I am Chinese"为例:

  • 用ANSI储存:12 Bytes
  • 用Unicode/UCS2储存:24 Bytes + 2 Bytes(header)
  • 用UCS4储存:48 Bytes + 4 Bytes(header)

以"我是中国人"为例:

  • 用ANSI储存:10 Bytes
  • 用Unicode/UCS2储存:10 Bytes + 2 Bytes(header)
  • 用UCS4储存:20 Bytes + 4 Bytes(header)

由此可见直接以Unicode/UCS的原始形式来储存是一种极大的浪费,而且也不利于互联网的传输(中文稍为合算一点。Unicode/UCS的压缩形式--UTF8出现了,套用官方网站的首句话『UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.』,由于UTF也适用于编码UCS,故亦可称为『UCS transformation formats (UTF)』

UTF8是以 8bits 即 1Byte 为编码的最基本单位,当然也可以有基于16bits和32bits的形式,分别称为UTF16和UTF32,但目前用得不多,而UTF8则被广泛应用在文件储存和网络传输中。

事实证明,对可以用ASCII表示的字符使用UNICODE并不高效,因为UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对他毫无用处。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即 UTF( U niversal T ransformation F ormat)。目前存在的UTF格式有:UTF-7, UTF-7.5, UTF-8, UTF-16, 以及 UTF-32。

UNICODE 来到时,一起到来的还有计算机网络的兴起,UNICODE 如何在网络上传输也是一个必须考虑的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8就是每次8个位传输数据,而UTF16就是每次16个位,只不过为了传输时的可靠性,从UNICODE到 UTF时并不是直接的对应,而是要过一些算法和规则来转换。

受到过网络编程的计算机僧侣们都知道,在网络里传递信息时有一个很重要的问题,就是对于数据高低位的解读方式,一些计算机是采用低位先发送的方法,例如我们PC机采用的 INTEL 架构,而另一些是采用高位先发送的方式,在网络中交换数据时,为了核对双方对于高低位的认识是否是一致的,采用了一种很简便的方法,就是在文本流的开始时向对方发送一个标志符——如果之后的文本是高位在前,那就发送"FEFF",反之,则发送"FFFE"。不信你可以用二进制方式打开一个UTF-X格式的文件,看看开头两个字节是不是这两个字节?( 这个好像还真不是,原文写错了??? )

关于utf8编码

UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8在ucs-4编码时最多可用到6个字节, ucs-2编码最多3个字节。

mysql中的utf8mb4最多占用4个字节, 普通汉字的utf8编码是3个字节

1字节: 0xxxxxxx

2字节: 110xxxxx 10xxxxxx

3字节: 1110xxxx 10xxxxxx 10xxxxxx

4字节: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

5字节: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

6字节: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

因此UTF-8中可以用来表示字符编码的实际位数最多有31位,即上表中x所表示的位。除去那些控制位(每字节开头的10等),这些x表示的位与UNICODE编码是一一对应的,位高低顺序也相同。

实际将UNICODE转换为UTF-8编码时应先去除高位0,然后根据所剩编码的位数决定所需最小的UTF-8编码位数。

因此那些基本ASCII字符集中的字符(UNICODE兼容ASCII)只需要一个字节的UTF-8编码(7个二进制位)便可以表示。

e.g: 我们在notepad++中输入"联通"并保存(默认为uft8格式), 然后查看其二进制位:

这两个汉字一共占用了6个字节, 每个汉字占3个字节, 普通的英文只占一个字节, 比如 输入"aben":

编码识别与转换的问题

讲到这里,我们再顺便说说一个很著名的奇怪现象:当你在windows 的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!呵呵,有人说这就是联通之所以拼不过移动的原因。

win10下保存时选择ANSI格式

其实这是因为GB2312编码与UTF8编码产生了编码冲撞的原因。

从网上引来一段从UNICODE到UTF8的转换规则,这里的unicode是使用2字节的unicode (ucs-2)。即ucs-2和utf-8的转换规则:

Unicode(ucs-2) Utf-8
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx

如果unicode是ucs-2,则utf-8的长度为1-3个字节;如果unicode是ucs-4,则utf-8的长度是1-6个字节,第一个字节的高位1的数目指明了这个utf-8的字符使用的byte数目。

例如"汉"字的Unicode编码是6C49。6C49在0800-FFFF之间,所以要用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 1100 0100 1001,将这个比特流按三字节模板的分段方法分为0110 110001 001001,依次代替模板中的x,得到:1110-0110 10-110001 10-001001,即E6 B1 89,这就是其UTF8的编码。

而当你在window记事本中保存文件时选择了ANSI格式,那么他实际就是GB系列的编码方式,在这种编码下,"联通"的内码是:"c1 aa cd a8":

在notepad++下查看二进制格式:

c1: 1100 0001

aa: 1010 1010

cd: 1100 1101

a8: 1010 1000

注意到了吗?第一二个字节、第三四个字节的起始部分的都是"110"和"10",正好与UTF8规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF8编码的文件,让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010",不好意思,这是UNICODE的006A,也就是小写的字母"j",而之后的两字节用UTF8解码之后是0368,这个字符什么也不是。这就是只有"联通"两个字的文件没有办法在记事本里正常显示的原因。

而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码又不出现了。

下面给出ucs-4和utf-8的转化关系:

Unicode(ucs-4) Utf-8
0000 0000 - 0000 007F 0xxxxxxx
0000 0080 - 0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF 1111110x 10xxxxxx 10xxxxxx

编码步骤:

  1. 首先确定需要多少个8bits(octets)
  2. 按照上述模板填充每个octets的高位bits
  3. 把字符的bits填充至x中,字符顺序:低位→高位,UTF8顺序:最后一个octet的最末位x→第一个octet最高位x
  4. 解码的原理一样。

在SQL Server数据库里,有n前缀的字串类型就是UNICODE类型(比如nchar, nvarchar),这种类型中,固定用两个字节来表示一个字符,无论这个字符是汉字还是英文字母,或是别的什么。 例如:nvarchar就是具有n前缀的子串类型,是unicode类型。

如果你要测试"abc汉字"这个串的长度,在没有n前缀的数据类型里,这个字串是7个字符的长度,因为一个汉字相当于两个字符。而在有n前缀的数据类型里,同样的测试串长度的函数将会告诉你是5个字符,因为一个汉字就是一个字符。

效率

从上述编码原理中得出的结论是:

  1. 每个英文字母、数字所占的空间为1 Byte;
  2. 泛欧语系、斯拉夫语字母占2 Bytes;
  3. 汉字占3 Bytes。

UTF-8/16/32的问题:

可以这样理解UTF-8/16/32,UTF-16是最初的Unicode编码形式,其原理类似DBCS,但是显然2个字节并不能够将全世界语言完全编码;于是乎,UTF-32出现了,4字节的编码肯定是足够了,但是用着用着发现,有很多字符的编码其高位都是0,太浪费空间;于是乎UTF-8和UTF-16变异体出现了,其原理类似于MBCS,即使用变长字节对字符进行编码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于Unicode,UTF-8,GB编码详解 的相关文章

随机推荐

  • 短视频、直播程序、一对一社交app--老外们玩嗨的程序竟然多半来自“中国的程序猿们开发”...

    短视频 直播程序 一对一社交app 老外们玩嗨的程序竟然多半来自 中国的程序猿们开发 在过去的2017年可以说是中国短视频 直播程序 一对一社交app极为火爆的一年 国内市场的厮杀一直没有停止过 很多投资者在国内那是一片红海 短视频 直播程
  • STM32 学习笔记 -- Keil 5调试STM32控制器,出现错误提示“Error: Encountered an improper argument”的原因参考

    最近在使用MDK调试STM32控制器 当下载完成 需要使用ST LINK进行程序仿真时 MDK偶尔会出现错误提示 Error Encountered an improper argument 大概意思是说 错误 遇到不正确的参数 出现这种情
  • 音频放大器的设计

    摘要 进入21世纪以后 各种便携式的电子设备成为了电子设备的一种重要的发展趋势 从作为通信工具的手机 到作为娱乐设备的MP3播放器 已经成为差不多人人具备的便携式电子设备 所有这些便携式的电子设备的一个共同点 就是都有音频输出 也就是都需要
  • 微信小程序模板消息发送功能实现

    前言 发送微信模板消息首先需要用户去绑定openId和serverOpenId才能推送模板消息 1 微信配置项 1 微信小程序根据前端返回的code去获取unionId和openid 通过type 0的接口去请求 2 用户获取到unionI
  • JasperSoft Studio的使用(1)——软件介绍及创建空白模板

    最近工作中需要用到报表打印 像pdf中多个table的展示 一个List在新的一页中显示列头等 JasperSoft 正好可以满足这些需求 所以记录一下 用以分享 软件介绍 JasperSoft Studio是一个面向 JasperRepo
  • 华为Java社招面试经历详解【已拿到offer】

    这篇文章主要介绍了华为Java社招面试经历 详细记录了华为java面试的流程 相关面试题与参考答案 需要的朋友可以参考下 看看自己能答对多少 如果能回答70 的题目 就大胆去阿里以及各互联网公司试试身手吧 本篇建议大家收藏 备用 华为Jav
  • Qt Creator release版本进行调试

    一 背景 我们在进行性Qt Creator 进行开发时 想要调试代码 通常是只需要编译 debug 版本的程序 但对于很多大型项目 引用外部第三方库中难免只存在release版本的动态库 所以 当我们的程序进行debug 调试时 往往会编译
  • window零基础部署langchain-ChatGLM

    一 介绍 从0开始安装运行langchain ChatGLM 6b int4模型 主要是版本要配套不然特别容易报错 我的机器配置CPU是Intel Core i7 7700HQ CPU 2 80GHz 2 80 GHz GPU8G 二 相关
  • 腾讯 13 年,我所总结的Code Review终极大法

    关注并星标腾讯云开发者 每周1 鹅厂工程师带你审判技术 第3期 林强 Code Review 我都 CR 些什么 谚语曰 Talk Is Cheap Show Me The Code 知易行难 知行合一难 嘴里要讲出来总是轻松 把别人讲过的
  • 蓝桥杯C/C++省赛:颠倒的价牌

    目录 题目描述 思路分析 AC代码 题目描述 小李的店里专卖其它店中下架的样品电视机 可称为 样品电视专卖店 其标价都是4位数字 即千元不等 小李为了标价清晰 方便 使用了预制的类似数码管的标价签 只要用颜色笔涂数字就可以了 这种价牌有个特
  • Java之美[从菜鸟到高手演变]之设计模式四

    在阅读过程中有任何问题 请及时联系 egg 邮箱 xtfggef gmail com 微博 http weibo com xtfggef 转载请说明出处 http blog csdn net zhangerqing 其实每个设计模式都是很重
  • html表格标签使用与注意事项

    表格的基本标签 场景 在网页中以行 列的单元格的方式整齐展示和数据 如 学生成绩表 基本标签 标签名 作用 table 表格的整体 用于包含多个tr tr 表格的每行 用于包含多个td td 表格单元格 用于包含内容 注意事项 嵌套关系为
  • 微信小程序分包加载,分包加载的优势

    微信小程序分包加载 有时候我们的小程序太大 首次打开小程序的时候会比较慢 可以进行分包处理 按照功能的划分 拆分成几个分包 让用户在操作小程序的时候按需下载资源 用户在进入某些页面的时候才去下载相应的资源 加载这个功能对应的分包 使用分包可
  • springboot设置logback-spring.xml的加载路径

    springboot将应用程序打包成jar以后 默认是将logback spring xml放在jar包里面根路径下 图 如果我们需要springboot加载jar包外部的logback spring xml应该怎么做了 例如我们想加载与x
  • shuffle机制详解

    将map输出作为输入传递给reducer的过程称为shuffle Shuffle过程包含在Map和Reduce两端 map阶段大致过程为 写数据 分区 排序 将属于同一分区的输出合并一起写在磁盘上 每个map任务都有一个环形内存缓冲区用于存
  • 服务里面找不到MySQL

    今天在连接数据库时发现自己的数据库出现了问题 在命令窗口输入 net start mysql 命令 还是启动不了 发现在服务里面竟然没有mysql服务了 1 以管理员身份运行cmd 切换到mysql安装目录的bin路径下 2 运行命令 my
  • C++构造函数简单实现电梯控制程序

    对于电梯 属性之一就是位置 所以要实现这一程序 要设置电梯的初始位置和按下电梯按钮改变的电梯的位置 代码如下 include
  • 【Linux】利用云服务器搭建云盘替代百度网盘、OneDrive等,docker安装seafile服务端,实现网页端上传下载,本地Linux、Windows安装客户端实时同步

    写在前面 博主使用OneDrive比较多 教育版有1t的大小 但是由于OneDrive在Linux系统中通过API不能连接学校的教育版 因此迫切需要一个云盘来替代OneDrive 由于之前也使用过Seafile 因此考虑使用Seafile搭
  • 编辑器正则替换px为rem

    正则部分 d d px 被替换部分 calc 1rem 100 注 此方法只能替换原css文件内无calc 运算的
  • 关于Unicode,UTF-8,GB编码详解

    内容来自网络 有部分修正 一 首先我们需要明白关于字符 character 字符集 character set 字符编码方式 character encoding 的概念 字符 字符是抽象的最小文本单位 它没有固定的形状 可能是一个字形 而