Java编码算法

news2024/11/24 14:34:23

编码

  • 1.编码算法
  • 2.URL编码
    • **URLEncoder类,主要进行编码**
    • **URLDecoder类,主要进行解码**
  • 3.Base64编码
    • Base64编码
    • Base64的补充字符
    • Base64的占位符
    • Base64的应用
  • 结论:

1.编码算法

什么是编码?

ASCII码就是一种编码,字母A的编码是十六进制的0x41,字母B是0x42,以此类推:

字母ASCII编码
A0x41
B0x42
C0x43
D0x44

因为ASCII编码最多只能有127个字符,要想对更多的文字进行编码,就需要用占用2个字节的Unicode或者3个字节的UTF-8。例如:中文的"中"字使用Unicode编码就是0x4e2d,UTF-8编码是0xe4b8ad。

汉字Unicode编码UTF-8编码
0x4e2d0xe4b8ad
0x65870xe69687
0x7f160xe7bc96
0x78010xe7a081

因此,最简单的编码是直接给每个字符指定一个若干字节表示的整数,复杂一点的编码就需要根据一个已有的编码推算出来。

2.URL编码

URL编码是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分,例如:
https://www.baidu.com/s?wd=%E4%B8%AD%E6%96%87
之所以需要URL编码,是因为出于兼容性考虑,很多服务器只识别ASCII字符。但如果URL中包含中文、日文这些非ASCII字符怎么办?不要紧,URL编码有一套规则:
如果字符是AZ,az,0~9以及-、_、.、*,则保持不变;

如果是其他字符,先转换为UTF-8编码,然后对每个字节以%XX表示。

例如:字符"中"的UTF-8编码是0xe4b8ad,因此,它的URL编码是%E4%B8%AD。URL编码总是大写。
Java标准库提供了一个URLEncoder类来对任意字符串进行URL编码:

import java.net.URLEncoder;
public class Main {
    public static void main(String[] args) {
        String encoded = URLEncoder.encode("中文!", "utf-8");
		System.out.println(encoded);
    }
}

上述代码的运行结果是%E4%B8%AD%E6%96%87%21,"中"的URL编码是%E4%B8%AD,"文"的URL编码是%E6%96%87,!虽然是ASCII字符,也要对其编码为%21。
如果服务器收到URL编码的字符串,就可以对其进行解码,还原成原始字符串。Java标准库的URLDecoder就可以解码:

public class Main {
    public static void main(String[] args) {
        String decoded = URLDecoder.decode("%E4%B8%AD%E6%96%87%21", "utf-8");
		System.out.println(decoded);
    }
}

要特别注意:URL编码是编码算法,不是加密算法。URL编码的目的是把任意文本数据编码为%前缀表示的文本,编码后的文本仅包含AZ,az,0~9,-,_,.,*和%,便于浏览器和服务器处理。

URLEncoder类,主要进行编码

String keyworld = "巴黎";
String encoderString = URLEncoder.encode(keyworld, "utf-8");
System.out.println("编码内容为:" + encoderString);

URLDecoder类,主要进行解码

String decoderString = URLDecoder.decode(encoderString, "utf-8");
System.out.println("解码内容为:" + decoderString);

3.Base64编码

URL编码是对字符进行编码,表示成%xx的形式,而Base64编码是对二进制数据进行编码,表示成文本格式。
Base64编码可以把任意长度的二进制数据变为纯文本,并且纯文本内容中且只包含指定字符内容:AZ、az、0~9、+、/、=。它的原理是把3字节的二进制数据按6bit一组,用4个整数表示,然后查表,把整数用索引对应到字符,得到编码后的字符串。
6位整数的范围总是063,所以,能用64个字符表示:字符AZ对应索引025,字符az对应索引2651,字符09对应索引52~61,最后两个索引62、63分别用字符+和/表示。
举个例子:3个byte数据分别是e4、b8、ad,按6bit分组得到十六进制39、0b、22和2d,分别对应十进制57、11、34、45,通过索引计算结果为5Lit4

┌───────────────┬───────────────┬───────────────┐
│      e4       │      b8       │      ad       │
└───────────────┴───────────────┴───────────────┘
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│111001001011100010101101│二进制
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
┌───────────┬───────────┬───────────┬───────────┐
│    390b     │    222d     │十六进制
└───────────┴───────────┴───────────┴───────────┘
┌───────────┬───────────┬───────────┬───────────┐
│    57113445     │十进制
└───────────┴───────────┴───────────┴───────────┘
┌───────────┬───────────┬───────────┬───────────┐
│    5L      │    i      │    t      │十进制
└───────────┴───────────┴───────────┴───────────┘

在Java中,二进制数据就是byte[]数组。Java标准库提供了Base64来对byte[]数组进行编解码:

public class Main {
    public static void main(String[] args) {
        byte[] input = new byte[] { (byte) 0xe4, (byte) 0xb8, (byte) 0xad };
        String b64encoded = Base64.getEncoder().encodeToString(input);
        System.out.println(b64encoded);
    }
}

编码后得到字符串结果:5Lit。要对这个字符使用Base64解码,仍然用Base64这个类:

public class Main {
    public static void main(String[] args) {
        byte[] output = Base64.getDecoder().decode("5Lit");
        System.out.println(Arrays.toString(output)); // [-28, -72, -83]
    }
}

因为标准的Base64编码会出现+、/和=,所以不适合把Base64编码后的字符串放到URL中。一种针对URL的Base64编码可以在URL中使用的Base64编码,它仅仅是把+变成-,/变成_:

public class Main {
    public static void main(String[] args) {
        // 原始字节内容
		byte[] input = new byte[] { 0x01, 0x02, 0x7f, 0x00 };
		
		// 分别使用两种方式进行编码
		String b64Encode = Base64.getEncoder().encodeToString(input);
        String b64UrlEncoded = Base64.getUrlEncoder().encodeToString(input);
        
        // 替换“+、/和=”
        System.out.println(b64Encode); 
        System.out.println(b64UrlEncoded);
        
        // 分别使用两种方式进行重新解码
        byte[] output1 = Base64.getDecoder().decode(b64Encode);
        byte[] output2 = Base64.getUrlDecoder().decode(b64UrlEncoded);

        // 结果完全一致
        System.out.println(Arrays.toString(output1));
        System.out.println(Arrays.toString(output2));
    }
}

Base64编码的目的是把二进制数据变成文本格式,这样在很多文本中就可以处理二进制数据。例如,电子邮件协议就是文本协议,如果要在电子邮件中添加一个二进制文件,就可以用Base64编码,然后以文本的形式传送。
Base64编码的缺点是传输效率会降低,因为它把原始数据的长度增加了1/3。和URL编码一样,Base64编码是一种编码算法,不是加密算法。
如果把Base64的64个字符编码表换成32个、48个或者58个,就可以使用Base32编码,Base48编码和Base58编码。字符越少,编码的效率就会越低。

Base64编码

String s = "中";
// 原始字符串转字节数组
byte[] bytes = s.getBytes("UTF-8");
System.out.println(Arrays.toString(bytes));
// Base64编码(JDK1.8后提供)
String encode64 = Base64.getEncoder().encodeToString(bytes);
System.out.println("base64编码后:" + encode64);

在这里插入图片描述

Base64的补充字符

String str = "ab";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
String enodingString = Base64.getEncoder().encodeToString(bytes);
System.out.println(enodingString);

在这里插入图片描述

Base64的占位符

// Base64的"="占位符
// 原始字节内容
byte[] input = new byte[] { 0x01, 0x02, 0x7f, 0x00 };
// 分别使用两种方式进行编码
String b64Encode = Base64.getEncoder().encodeToString(input);
String b64UrlEncoded = Base64.getUrlEncoder().encodeToString(input);

// 替换“+、/和=”
System.out.println(b64Encode);
System.out.println(b64UrlEncoded);

// 分别使用两种方式进行重新解码
byte[] output1 = Base64.getDecoder().decode(b64Encode);
byte[] output2 = Base64.getUrlDecoder().decode(b64UrlEncoded);

// 结果完全一致
System.out.println(Arrays.toString(output1));
System.out.println(Arrays.toString(output2));

在这里插入图片描述

Base64的应用

xx.jpg文件读取内容信息,编码,保存为base64的xx.txt文件

将xx.txt文件读取,解码,保存为xx.jpg文件

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

//Base64应用:xx.jpg文件读取内容信息,编码,保存为base64的xx.txt文件
//将xx.txt文件读取,解码,保存为xx.jpg文件
public class Main {
	public static void main(String[] args) throws IOException {
		imgEcoding();
		imgDecoding();
	}

	private static void imgEcoding() throws IOException {
		byte[] b = Files.readAllBytes(Paths.get("E:\\apesourcefile\\maomao.jpg"));
		// 将二进制字节信息用base64编码
		String str = Base64.getEncoder().encodeToString(b);
		// 写出编码后的字符串
		Files.write(Paths.get("a.txt"), str.getBytes());
		System.out.println("图片base64信息保存成功");
	}

	private static void imgDecoding() throws IOException {
		// base64字符串对应的字节信息
		byte[] b = Files.readAllBytes(Paths.get("a.txt"));
		// 解码
		byte[] bytes = Base64.getDecoder().decode(b);
		Files.write(Paths.get("E:\\apesourcefile\\Base64.jpg"), bytes);
		System.out.println("base64解码图片成功");
	}
}

在这里插入图片描述

结论:

URL编码和Base64编码都是编码算法,它们不是加密算法;
URL编码的目的是把任意文本数据编码为%前缀表示的文本,便于浏览器和服务器处理;
Base64编码的目的是把任意二进制数据编码为文本,但编码后数据量会增加1/3。

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

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

相关文章

C语言典型例题28

《C程序设计教程(第四版)——谭浩强》 习题2.5 输入一个华氏温度,要求输出摄氏温度。公式为C5/9(F-32),要求输出要有文字说明,取两位小数 数学知识: (1)华氏温度与摄氏温度&#x…

MySQL(六):mysql 约束

基本介绍:约束用于确保数据库的数据满足特定的商业规则,约束包括:not null、unique、primary key、foreign key 、check五种。 一、主键的使用(primary key) 字段名 字段类型 primary key用于唯一的表示表行的数据,当…

SpringBoot基础 第二天

SpringBoot对静态资源的映射: (1) 要在src/main/resources文件夹下创建static和templates两个文件夹staitc存储静态资源,templates存储模板引擎 (2)要在pom.xml依赖下导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>…

VS项目打包成lib库并使用

一、新建一个静态库项目 一般要把项目设为Release模式 二、添加文件 将所需要打包的头文件、源文件添加到该静态库项目中 三、生成项目 生成成功后即可在Release文件夹出现找到相应的.lib文件 四、使用静态库 将静态库文件复制到项目文件夹中&#xff0c;然后在项目属性设…

LSV实验——部署DR模式集群

目录 一、实验环境 二、配置 1、LVS 2、router 3、client 4、RS 三、配置策略 1.Director服务器采用双IP桥接网络&#xff0c;一个是VPP&#xff0c;一个DIP 2.Web服务器采用和DIP相同的网段和Director连接 3.每个Web服务器配置VIP 4.每个web服务器可以出外网 一、实验环…

CENTOS9+RSYSLOG+LOGROTATE收集日志

系统版版本为CentOS Stream release 9 rsyslog和lograte通常系统已经安装了。 #rpm -qa | grep rsyslog rsyslog-logrotate-8.2310.0-4.el9.x86_64 rsyslog-8.2310.0-4.el9.x86_64 rsyslog-gnutls-8.2310.0-4.el9.x86_64 rsyslog-gssapi-8.2310.0-4.el9.x86_64 rsyslog-relp-…

常见中间件漏洞(三、Jboss合集)

目录 三、Jboss Jboss介绍 3.1 CVE-2015-7501 漏洞介绍 影响范围 环境搭建 漏洞复现 3.2 CVE-2017-7504 漏洞介绍 影响范围 环境搭建 漏洞复现 3.3 CVE-2017-12149 漏洞简述 漏洞范围 漏洞复现 3.4 Administration Console弱囗令 漏洞描述 影响版本 环境搭建…

Netty技术全解析:ByteToMessageCodec类深度解析

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

Qt/C++最新地图组件发布/历时半年重构/同时支持各种地图内核/包括百度高德腾讯天地图

一、前言说明 最近花了半年时间&#xff0c;专门重构了整个地图组件&#xff0c;之前写的比较粗糙&#xff0c;有点为了完成功能而做的&#xff0c;没有考虑太多拓展性和易用性。这套地图自检这几年大量的实际项目和用户使用下来&#xff0c;反馈了不少很好的建议和意见&#…

【技巧】IDEA 个性化配置

【技巧】IDEA 个性化配置 自动补全 关闭大小写区分 自动导包 插件 Rainbow Brackets 彩色括号 更容易区分是哪个括号

【LVS】负载均衡之NAT模式

一、LVS概念 LVS&#xff08;Linux Virtual Server&#xff09;是一个基于Linux操作系统的虚拟服务器技术&#xff0c;用于实现负载均衡和高可用性。LVS通过将客户端的请求分发到多台后端服务器上&#xff0c;从而提高整体服务的处理能力和可靠性。 二、LVS优势 高性能&…

Centos安装OpenJDK

使用yum包管理器搜索可用的OpenJDK包 sudo yum search openjdk根据你的需求选择合适的OpenJDK版本进行安装 sudo yum install java-1.8.0-openjdk.x86_64安装完成后&#xff0c;验证安装是否成功 java -version

MS2201BP以太网收发电路

MS2201BP 是吉比特以太网收发器电路&#xff0c;可以实现 超高速度的全双工数据传输。它的通信遵从 IEEE 802.3 Gigabit Ethernet 协议中的 10 比特接口的时序要求协 议 。 MS2201BP 支 持 数 据 传 输 速 率 从 1Gbps 到 1.85Gbps 。 主要特点 ◼ 电源电压&#xff…

实验24.创建并挂载文件系统

已完成实验 已完成实验链接 简介 实验 24. 创建并挂载文件系统 总结 创建文件系统: 初始化每一个分区的结构&#xff0c;把扇区划分为超级块&#xff0c;扇区位图&#xff0c;inode 位图&#xff0c;inode 表&#xff0c;根目录&#xff0c;空闲扇区 挂载分区: 创建一个分…

学习STM32(4)--STM32单片机定时器的应用

1 引 言 在STM32单片机的开发中&#xff0c;定时器是一个非常重要的模块&#xff0c;可以用于实现精准的时间控制和周期性的任务。在STM32F103系列单片机中&#xff0c;常见的定时器包括基本定时器、通用定时器和高级定时器。 2 实验目的 1.掌握STM32F103的基本定时器的使…

HAL库源码移植与使用之ADC

ADC类型&#xff1a; F1 F4 H4 H7用的都是逐次递进式 ADC电气特性&#xff1a; 该ADC只能承受3.6v以下电压 F1时钟不能超过14Mhz 流程顺序&#xff1a;先配置好1参考电压和芯片电源&#xff0c;再配置2电压输入通道并通过模拟多路开关选择通路到注入通道或规则通道&#xff0…

Spring AI -快速开发ChatGPT应用

Spring AI介绍 Spring AI是AI工程师的一个应用框架&#xff0c;它提供了一个友好的API和开发AI应用的抽象&#xff0c;旨在简化AI应用的开发工序&#xff0c;例如开发一款基于ChatGPT的对话、图片、音频等应用程序。 Spring AI已经集成了OpenAI的API&#xff0c;因此我们不需…

【虚拟化】KVM使用virt-manager部署及管理虚拟机

目录 一、KVM 概述 二、KVM工作原理 三、部署KVM 四、新建虚拟机步骤 4.1 创建存储池并创建存储卷 4.1.1 创建存储池 4.1.2 创建存储卷 4.3 创建ISO存储池 4.4 生成新的虚拟机 一、KVM 概述 KVM 是 Kernel-based Virtual Machine 的缩写&#xff0c;是一种用于虚拟化的…

LeetCode LCR147.最小栈

LeetCode LCR147.最小栈 思路&#x1f914;&#xff1a; 建立两个栈&#xff0c;一个栈正常入栈出栈&#xff0c;一个栈只用于出入最小数&#xff0c;当push值小于minst栈顶才入栈&#xff0c;当pop值等于minst栈顶才出栈。 代码&#x1f50e;&#xff1a; class MinStack { pu…

如何通过JavaScript提升逻辑判断的可读性?

在前端开发过程中&#xff0c;我们经常会遇到需要根据不同条件执行不同逻辑的场景。对于初学者来说&#xff0c;这样的逻辑判断可能会导致代码冗长且难以维护。那么&#xff0c;如何才能写出既简洁又易读的代码呢&#xff1f;本文将带你逐步优化 JavaScript 中的条件判断&#…