简析多种编码方式(Hex, Base64, UTF-8)
首先计算机只认得二进制,0和1,所以我们现在看到的字都是经过二进制数据编码后的;计算机能针对0和1的组合做很多事情,这些规则都是人定义的;然后有了字节的概念,8比特一个字节,如01011100就是一个字节;
人定义好计算机的0和1的数据结构做事的时候,如果每个人都用不同的数据结构,不同的定义,就会使得人和人之间让计算机做的事无法统一,也导致无法通讯,所以要一起共同定义一套大家都认同的规则,其中ASCii码就是最初始的交换码,用做记录信息、交互信息的;
相同的字节串不同的编码就会有不同的展示,只有正确的编码才能表达出字符串本身要记载的信息,而信息是面向人的,只有人能识别,才叫信息,只是偶尔被计算机理解;
字节、字符与字符串:
字节是8比特位构成,上传已经说了;
字符是用字节构成的,但多少字节,怎么构成我们认识的唯一的字符?这个由编码格式决定,也就是Unicode、GBK,(为啥要用字节?,因为历史觉得8比特很牛逼啊)
字符串是字符的序列,各种计算机语言不同表示,如Redis就和C的字符串不一样,C是以 ‘\0’ 结尾;我们说的对字符的编码,而不是字符串;
Hex用字符串形式看二进制代码:
首先,二进制文件通常不易于人看,因为人会看眼花,所以必须转为其他进制,16进制是最好的,刚好2字符表示一个字节
Hex编码是以4比特作为一个单位编码,用4是因为计算机进位是2的倍数,而为了能把比特串分割开来,最适中就是取16进制;所以Hex编码就是16进制编码;用于人类比用比特更直观简介的方式看待比特串(马上反应过来比特串),当然取更多位不适合人口算;
然后我们就有了WinHex这个工具的命名;用它修复二进制文件很不错,前提你对该文件二进制构表(一般是具有协议去解析二进制的,我称之为构表协议吧)很熟;
Base64是面向网络的,其实性质也是这样;
Unicode、GBK都是字符串编码:
看到知乎一个alipay的说啥编码和编码格式不同,gbk是unicode的编码格式,简直笑死人;
字符是独一无二的,人类符号系统抽象的产物,世界唯一,全世界的字符构成字符集,字符也是在演进的;而Unicode和GBK等都是字符的一种编码;也就是一个二进制比特串(数字)和字符的映射表;
Java内部是Unicode默认,以及其面向字符、面向字节:
对于一个抽象字符,在Java中的二进制表示当然需要编码,用的就是Unicode,如果源文件存储并非Unicode怎么办呢?当然需要转换,因此Java很多面向字符流的I/O其实都是默认有转换规则存在;
这里提下I/O都分面向字节和字符,其实面向字节就是不管编码,而面向字符是带编码转换,是的一个抽象字符串如 “饭” 是在哪种编码格式都表示 “饭”,因此面向字符I/O指定编码格式很重要,一般不指定采用默认,如win操作系统默认GBK,而linux默认UTF-8;
UTF-8和Unicode是哈夫曼编码:
自己去查一下吧,是哈夫曼编码转换的
Unicode
UTF-8
待补
Hex编码的编码原理:
* Hex编码的原理就是将原来8位的二进制字节打断,分成两个4位的,并且在前面加上4个零,
* 进行补位这样一个8位二进制字节就变成了2个8位的二进制字节,在将新得到的2个二进制字符进行16位进制转换
* 得到的新的16位字符串就是Hex的值,所以 二进制的[72, 69, 88] 《hex》 484558是相等的。
* [72, 69, 88]byte数组的二进制=01001000 01000101 01011000
* 二进制=01001000 01000101 01011000 进行hex的打断操作 0100 1000 0100 0101 0101 1000
* 在加上前面的4个零得到一个新的6个8位二进制 = 00000100 00001000 00000100 00000101 00000101 00001000
* 新的6个8位二进制 进行16进制转换 00000100 00001000 00000100 00000101 00000101 00001000 = 484558
* 总结所以说Hex编码后的二进制长度变为了原来的2倍,所以字节长度增加了一倍。
Hex的编码过程
字符串: HEX
ASCII码: [72,69,88]
二进制码: 01001000 01000101 01011000
重新分组: 0100 1000 0100 0101 0101 1000
高位补零后的二进制码: 00000100 00001000 00000100 00000101 00000101 00001000
十六进制码: 4 8 4 5 5 8
Hex码: 484558
Java 代码实现
package com.gl.test;
import org.apache.commons.codec.binary.Hex;
import java.util.Arrays;
public class TestHex {
public static void main(String[] args) {
//一个字符串
String hex = "HEX";
//获取字符串的byte数组
byte[] buf = hex.getBytes();
//输出byte数组
System.out.println(Arrays.toString(buf));
//转换成Hex输出
System.out.println(Hex.encodeHexString(buf));
}
}
maven 依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>