编码与解码

编码与解码

一、字节 & 字符

字节 Byte

  • 字节是计算机中常用的数据存储和传输单位,它是 8 位二进制数据。
  • 在Java中,字节数据类型是byte,它占用8位(一个字节)。

字符 Character

  • 字符是指人类可读的文本数据,通常是Unicode编码的一个字符。
  • 在Java中,字符数据类型是char,它占用16位(两个字节)。

不同编码的字节占用:

  • ASCIIISO-8859-1 中,数字、英文、标点占用一个字节,不支持汉字。
  • GBK 中,数字、英文、标点占用一个字节;汉字占用两个字节。
  • UTF-8 中,数字、英文、标点占用一个字节;汉字占用三个字节。

二、编码 & 解码

计算机中的信息都是用二进制数表示的,我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。

  • 编码 Encode:按照某种规则,将 字符 存储到计算机中。

  • 解码 Decode:将存储在计算机中的 二进制数据,按照某种规则解析显示出来。

按照A规则存储,同样按照A规则解析,就能显示正确的文本符号。反之,编码和解码采用不同的编码规则,就可能导致乱码

三、字符集 & 字符编码

不管是 编码 还是 解码,都需要参考一个规则。这个规则就是某一个编码表。

  • 字符集 Charset:一组字符的集合。
  • 字符编码 Character Encoding:将 字符集 中的 每个字符 映射为 二进制数据 的规则或算法。

常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

在这里插入图片描述

一套 字符集 对应着一套或多套 字符编码,而 一套 字符编码 属于一套 字符集

  • 可见,当指定了字符编码,它所对应的字符集自然就指定了。

四、ASCII

ASCII(American Standard Code for Information Interchange)美国标准信息交换代码。

  • ASCII 是一种基于 拉丁字母 的字符编码系统,用于在计算机系统中表示 文本数据 和 控制字符。
  • ASCII 定义了128个字符,包括英文字母(大写和小写)、数字、标点符号和一些控制字符。
  • ASCII 的 基本字符集,使用 7 位(bits)表示一个字符,共 128 字符。
  • ASCII 的 扩展字符集,使用 8 位(bits)表示一个字符,共 256 字符,方便支持欧洲常用字符。

下面为ASCII码表:

在这里插入图片描述

ASCII 编码:把 字符A 按照 ASCII表的规则 编码成 计算机中的二进制

字符A	  十进制	   二进制
'A' ---> 65 ---> 0100 0001  

ASCII 解码:把 计算机中的二进制 按照 ASCII表的规则 解码成 字符A

  二进制	   十进制      字符A
0100 0001 ---> 65 -----> 'A' 

五、ISO-8859-1

ISO(International Standards Organization)国际标准化组织。

ISO-8859-1 是 ISO 发布的第一个 8 位字符集标准,包含 256 个字符,其中前 128 个字符与 ASCII 相同。

  • 0-127:与 ASCII 完全相同,包含基本的英文字母、数字和控制字符。
  • 128-255:包括一些常用的拉丁字母、符号和一些特殊字符,适合大多数西欧语言,如德语、法语、西班牙语等。

六、GB

由于 ASCII 字符集 不支持中文,因此,汉字编码字符集 GB(国标)应运而生。

  • GB2312:前 128 个字符与 ASCII 相同,用两个字节表示汉字(包含约 7,000 个汉字和符号)
  • GBK:GB2312的升级版,包括了GB2312的所有内容,同时新增了近20000个新的汉字,包括繁体字和符号。
  • GB18030:GBK的升级版,包含了大部分的中文(简体、繁体、甲骨文、象形文等等),还有少数民族的文字,识别更多。

其中 GBK 是最常用的。

七、Unicode

1、概述

如果每个国家都定义一套自己的编码标准,结果相互之间谁也不懂谁的编码,就无法进行很好的沟通交流。

所以 ISO(国际标准化组织)定义一套编码方案来解决所有国家的编码问题,这个新的编码方案就叫做 Unicode。

Unicode字符集包含了几乎所有的已知语言的字符,包括各种字母、数字、标点符号、符号、控制字符、中文等。

2、发展

Unicode 字符集 与 ASCII 字符集 的不同之处在于,它使用了更多的位数来表示字符,以便支持更大的字符集。

  • 最早的版本使用16位(两个字节)来表示字符,称为 UCS-2 编码。
  • 后来随着扩展,采用了更多的位数,使用32位(四个字节)来表示字符,称为 UTF-32 编码。
  • 实际应用中,为了节省存储空间,常常使用可变长度的编码方案,例如 UTF-8 和 UTF-16 编码。

3、UTF-8 编码

可变长度编码,使用1~4个字节为每个字符编码

  • 1个字节:ASCII 字符(0-127)
  • 2个字节:拉丁文等字符
  • 3个字节:中文等字符
  • 4个字节:其他极少使用的Unicode辅助字符

4、UTF-16 编码

可变长度编码,通常使用 2 或 4 个字节表示一个字符。

优点

  • 对于许多常用的非英语字符(如汉字),占用的空间相对较小(通常为 2 字节)。
  • 处理时,某些操作可能更高效,因为字符通常是固定长度的(2 或 4 字节)。

缺点

  • 不兼容 ASCII,某些情况下可能需要额外处理。
  • 对于只使用 ASCII 字符的文本,可能会占用更多空间。

八、Base64 编码

1、概述

Base64 编码 是一种将 二进制数据 转换为 ASCII字符串 的编码方式(编码后的一组字符只包含 ASCII 可打印字符)

  • 通常用于在网络传输中以文本形式传输二进制数据,或者用于在文本协议中嵌入二进制数据。
  • 通常是由64个字符组成,包括26个大写字母、26个小写字母、10个数字以及一些特殊字符(+、/、= 等)

2、原理

  1. 输入:Base64 编码的输入是二进制数据,例如 文件内容 或 图像。
  2. 分组:将输入的二进制数据每 3 个字节(24 位)作为一组进行处理。
  3. 拆分:将 24 位的数据拆分为 4 个 6 位的部分。
  4. 映射:根据这 6 位的值在 Base64字符表 中查找对应的字符。
  5. 填充:如果输入的字节数不是 3 的倍数,会在输出末尾添加一个或两个 = 字符作为填充。

Base64 字符表如下(对应 6 位二进制)

ABCDEFGHIJKLMNOPQRSTUVWXYZ (0-25)
abcdefghijklmnopqrstuvwxyz (26-51)
0123456789 (52-61)
+ (62)
/ (63)

3、代码示例

import java.util.Base64;

public class Base64Example {
    public static void main(String[] args) {
        String originalString = "Hello, Base64!";
        String encodedString = Base64.getEncoder().encodeToString(originalString.getBytes());
        String decodedString = new String(Base64.getDecoder().decode(encodedString));

        System.out.println("Original: " + originalString);
        System.out.println("Encoded: " + encodedString);
        System.out.println("Decoded: " + decodedString);
    }
}

九、十六进制编码

Base64编码、AES加密的密文会经常出现/, 跟url里分隔用的/相同,可能会引起一些其它问题。

使用十六进制编码,密文只会存在数字和字母。

public class HexExample {
    public static void main(String[] args) {
        String originalString = "Hello, Hex!";
        String hexString = toHex(originalString.getBytes());
        byte[] bytes = fromHex(hexString);

        System.out.println("Original: " + originalString);
        System.out.println("Hex: " + hexString);
        System.out.println("Decoded: " + new String(bytes));
    }

    public static String toHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static byte[] fromHex(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                                 + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scj1022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值