消息队列篇--扩展篇--码表及编码解码(理解字符字节和二进制,了解ASCII和Unicode,了解UTF-8和UTF-16,了解字符和二进制等具体转化过程等)
1、理解字符,int,字节以及二进制存储
(1)、字符
字符是文本的基本单位,例如字母(A, B, C)、数字(1, 2, 3)、标点符号(!, ?, ,)以及其他符号(如特殊符号😊等)。
编码表示:
在计算机中,字符通过编码标准(如ASCII、Unicode)映射为特定的数值(称为“码点”或“代码点”)。
例如:
- 'A’的ASCII码点是65(ASCII)或U+0041(Unicode)。
- '你’的Unicode码点是U+4F60(Unicode)。
存储与处理:
字符为字符串的一部分,但也可以单独处理。例如,在Java中,字符用char类型表示,每个char占用2字节(UTF-16编码)。
示例:
char ch = 'A'; // 'A'的Unicode码点是U+0041
System.out.println((int) ch); // 输出65
(2)、基本数据类型int
int是Java中的一种基本数据类型,用于表示整数。它占用4字节(32 位),可以表示的范围是从-2,147,483,648到2,147,483,647。
用途:
int类型常用于数值计算、索引数组、计数等场景。它可以存储较大的整数值,适合大多数常见的数值运算。
示例:
char ch = 'A';
int codePoint = (int) ch; // 将字符'A'转换为其Unicode码点65
System.out.println(codePoint); // 输出65
(3)、字节(Byte)
字节(byte)是计算机中最小的可寻址数据单位,通常由8位(bit)组成。一个字节可以表示的范围是从0到255(无符号)或从-128到127(有符号)。
用途:
字节广泛用于文件读写、网络传输、内存操作等场景。它是计算机中最基本的数据存储单元。
示例:
byte b = 65; // 字节值65
System.out.println(b); // 输出65
字节与字符的关系:
字符在计算机中最终以字节形式存储。不同编码方式(如UTF-8、UTF-16)决定了如何将字符映射为字节序列。
例如:
- 'A’在UTF-8中表示单个字节65,在UTF-16中会开辟两个字节存储。
- '你’在UTF-8中表示为三个字节E4 BD A0。
示例:
String str = "你好";
byte[] utf8Bytes = str.getBytes(java.nio.charset.StandardCharsets.UTF_8);
for (byte b : utf8Bytes) {System.out.printf("%02X ", b); // 输出十六进制展示: E4 BD A0 E5 A5 BD
}
(4)、计算机中的二进制数据
二进制数据是计算机内部表示信息的基本方式,所有数据最终都以二进制形式存储和处理。二进制数据由一系列的位(bit)组成,每个位可以是0或1。
数据类型与二进制表示:
不同的数据类型在计算机中以不同的方式存储为二进制数据。
- 字符:通过编码标准(如UTF-8、UTF-16)转换为字节序列,每个字节由8位组成。
- 整数:直接存储为二进制形式。例如,整数65在二进制中表示为00000000 00000000 00000000 01000001(32位,因为一个int占用4个字节存储)。
示例:
int number = 65;
System.out.println(Integer.toBinaryString(number)); // 输出1000001
示例1:字符与二进制数据
假设我们有一个字符’A’,其Unicode码点是65。我们可以将其转换为二进制形式。
char ch = 'A';
int codePoint = (int) ch; // 获取 Unicode 码点
String binaryString = Integer.toBinaryString(codePoint);
System.out.println("Binary representation of 'A': " + binaryString); // 输出1000001
示例2:整数与二进制数据
假设我们有一个整数65,我们可以查看其二进制表示。
int number = 65;
String binaryString = Integer.toBinaryString(number);
System.out.println("Binary representation of 65: " + binaryString); // 输出 1000001
(5)、总结
- 字符是文本的基本单位,通过编码标准(如ASCII、Unicode)映射为特定的数值(码点)。字符在计算机中通常存储为字符串的一部分,但也可以单独处理。
- int是一种基本数据类型,用于表示整数,占用4字节(32位),适用于数值计算、索引数组等场景。字符可以通过强制转换为int来获取其对应的Unicode码点。
- 字节是计算机中最小的可寻址数据单位,由8位组成。字符在计算机中最终以字节形式存储,不同编码方式决定了如何将字符映射为字节序列。
- 二进制数据是计算机内部表示信息的基本方式,所有数据最终都以二进制形式存储和处理。不同数据类型在计算机中以不同的方式存储为二进制数据。
2、ASCII和Unicode
ASCII和Unicode是两种字符集编码标准,它们在设计目的、字符集范围和应用场合上有显著的区别。
(1)、ASCII (American Standard Code for Information Interchange)
1、定义与用途
ASCII是一种早期的字符编码标准,主要用于表示英文字母、数字和一些常见的符号。
- 用途:它广泛应用于早期的计算机系统中,特别是在美国和英语国家。
- 范围:ASCII定义了128个字符(从0到127),每个字符用一个字节(8位)中的低7位表示(最高位通常为0)。
2、字符集
基本字符:
- 控制字符:如换行(LF, U+000A)、回车(CR, U+000D)等不可见字符。
- 可打印字符:包括大写和小写字母(A-Z, a-z)、数字(0-9)、标点符号和其他常见符号(如 !, @, , $, % 等)。
3、编码方式
固定长度编码:每个字符占用1字节(8位),但只使用了低7位,因此实际上只用了7位(最高位为0)。
示例:
- 'A’的ASCII编码是41(十六进制)或01000001(二进制)。
- '!'的ASCII编码是21(十六进制)或00100001(二进制)。
完整ASCII码表:
(2)、Unicode
1、定义与用途
Unicode是一个全球通用的字符集标准,旨在为世界上几乎所有的书写系统中的每个字符分配一个唯一的编号(称为“码点”或“代码点”)。
- 用途:Unicode被设计用来解决不同语言和地区之间的字符编码问题,支持几乎所有现代语言以及许多历史上的语言和符号。
- 范围:Unicode包含超过140,000个字符,覆盖了从基本拉丁字母到复杂的象形文字等各种字符。
2、字符集
- 基本多文种平面(BMP):包含最常见的字符,范围从U+0000到U+FFFF,涵盖了大多数常用字符。
- 补充平面:用于表示超出BMP的字符,范围从U+10000到U+10FFFF,包括表情符号、古代文字等。
3、编码方式
变长编码:Unicode本身并不是一种具体的编码格式,而是通过UTF-8、UTF-16等具体编码格式来实现。
- UTF-8:变长编码,兼容ASCII。对于单字节字符(如英文字符),UTF-8使用1字节;对于多字节字符(如中文字符),UTF-8可能使用2到4字节。
- UTF-16:变长编码,主要使用2字节表示BMP中的字符,对于超出BMP的字符使用4字节(代理对)。
(3)、主要区别
(4)、示例对比
1、ASCII字符
假设我们有一个简单的ASCII字符串"Hello!"。
ASCII编码结果:
‘H’ -> 48(十六进制)或01001000(二进制)
‘e’ -> 65(十六进制)或01100101(二进制)
‘l’ -> 6C(十六进制)或01101100(二进制)
‘o’ -> 6F(十六进制)或01101111(二进制)
‘!’ -> 21(十六进制)或00100001(二进制)
2、Unicode字符
假设我们有一个包含中文字符的字符串"你好"。
Unicode码点:
‘你’ -> U+4F60
‘好’ -> U+597D
UTF-8编码:
‘你’ -> E4 BD A0(三字节)
‘好’ -> E5 A5 BD(三字节)
UTF-16编码:
‘你’ -> 4F60(两字节)
‘好’ -> 597D(两字节)
(5)、Java示例
1、ASCII字符编码
public class AsciiExample {public static void main(String[] args) {String originalString = "Hello!";// 使用 ASCII 编码将字符串转换为字节数组byte[] asciiBytes = originalString.getBytes(java.nio.charset.StandardCharsets.US_ASCII);System.out.println("Encoded with ASCII:");for (byte b : asciiBytes) {System.out.printf("%02X ", b);}}
}
输出示例:
Encoded with ASCII:
48 65 6C 6C 6F 21
2、Unicode字符编码
import java.nio.charset.StandardCharsets;public class UnicodeExample {public static void main(String[] args) {String originalString = "你好";// 使用 UTF-8 编码将字符串转换为字节数组byte[] utf8Bytes = originalString.getBytes(StandardCharsets.UTF_8);System.out.println("Encoded with UTF-8:");printByteArray(utf8Bytes);// 使用 UTF-16 编码将字符串转换为字节数组byte[] utf16Bytes = originalString.getBytes(StandardCharsets.UTF_16);System.out.println("Encoded with UTF-16:");printByteArray(utf16Bytes);}private static void printByteArray(byte[] bytes) {for (byte b : bytes) {System.out.printf("%02X ", b);}System.out.println();}
}
输出示例:
Encoded with UTF-8:
E4 BD A0 E5 A5 BD
Encoded with UTF-16:
FE FF 4F 60 59 7D
(6)、ASCII和Unicode总结
- ASCII是一种早期的字符编码标准,仅支持128个字符,主要用于表示英文字母、数字和一些常见的符号。它的优点是简单且高效,但只能处理有限的字符集。
- Unicode是一个全球通用的字符集标准,旨在为世界上几乎所有的书写系统中的每个字符分配一个唯一的编号。它通过UTF-8、UTF-16等具体编码格式实现,能够支持多种语言和符号,适用于现代计算机系统中的多语言文本处理。
通过理解这些区别,你可以根据实际需求选择合适的字符编码方式。对于纯英文文本,ASCII或UTF-8都是非常高效的选择;而对于多语言文本,UTF-8或UTF-16更加适合。
3、UTF-8、UTF-16和Base64
UTF-8和UTF-16是Unicode字符集的具体编码实现,用于将Unicode码点转换为字节序列以便在计算机系统中存储和传输。
Base64是一种二进制到文本的编码方法,主要用于将任意二进制数据转换为ASCII字符串格式。
(1)、UTF-8编码
UTF-8是一种变长编码格式,兼容ASCII。可以根据字符的不同范围使用不同数量的字节来表示Unicode码点。UTF-8可以使用1到4字节来表示不同的字符。
变长编码理解下:
如UTF-8是一种变长编码格式,这意味着它可以根据字符的不同范围使用不同数量的字节来表示Unicode码点。
固定长度的编码格式:
与变长编码相对应的是固定长度的编码格式,这些编码方式对每个字符使用相同数量的字节进行表示。常见的固定长度编码方式有ASCII编码、UTF-32等。UTF-32每个字符占用4字节,能够表示所有Unicode码点,但占用更多存储空间;ASCII每个字符占用1字节,仅支持128个字符,主要用于英语和西欧语言。
对比:
具体规则:
单字节字符(ASCII字符):
- 范围:U+0000到U+007F
- 示例:‘A’ (U+0041)在UTF-8中表示为41(1字节)
双字节字符:
- 范围:U+0080到U+07FF
- 示例:‘é’ (U+00E9)在UTF-8中表示为C3 A9(2字节)
三字节字符:
- 范围:U+0800到U+FFFF
- 示例:‘你’ (U+4F60)在UTF-8中表示为E4 BD A0(3字节)
四字节字符:
- 范围:U+10000到U+10FFFF
- 示例:表情符号😊(U+1F60A)在UTF-8中表示为F0 9F 98 8A(4字节)
示例代码:
import java.nio.charset.StandardCharsets;public class Utf8Example {public static void main(String[] args) {// 字符 '你'String bmpStr = "你";byte[] utf8BytesBmp = bmpStr.getBytes(StandardCharsets.UTF_8);System.out.println("BMP character: " + bmpStr);System.out.print("UTF-8 encoding (hex): ");for (byte b : utf8BytesBmp) {System.out.printf("%02X ", b);}System.out.println();// 补充平面字符 😊String emojiStr = "😊";byte[] utf8BytesEmoji = emojiStr.getBytes(StandardCharsets.UTF_8);System.out.println("Supplementary character: " + emojiStr);System.out.print("UTF-8 encoding (hex): ");for (byte b : utf8BytesEmoji) {System.out.printf("%02X ", b);}System.out.println();}
}
输出示例:
BMP character: 你
UTF-8 encoding (hex): E4 BD A0
Supplementary character: 😊
UTF-8 encoding (hex): F0 9F 98 8A
(2)、UTF-16编码
UTF-16是一种变长编码格式,主要用于将Unicode码点转换为字节序列。它主要使用16位(2字节)来表示Unicode的基本多文种平面(BMP,Basic Multilingual Plane),即从U+0000到U+FFFF范围内的字符。对于超出BMP的字符(即从U+10000到U+10FFFF),UTF-16使用32位(4字节)表示,通过所谓的“代理对”(surrogate pairs)实现。
具体规则:
BMP字符:
- 对于码点在U+0000到U+FFFF范围内的字符,UTF-16直接只用两个字节,即一个16位二进制值来表示。
- 例如,字符’你’的Unicode码点是U+4F60,在UTF-16中直接表示为4F60。
补充平面字符:
- 对于码点在U+10000到U+10FFFF范围内的字符,UTF-16使用4个字节即2个16位二进制值(称为“代理对”)来表示。
- 这两个16位值分别是一个高代理(High Surrogate)和一个低代理(Low Surrogate)。
- 高代理范围:D800到DBFF
- 低代理范围:DC00到DFFF
- 例如,表情符号😊的Unicode码点是U+1F60A,在UTF-16中表示为两个char:高代理D83D和低代理DE0A。
示例代码:
public class Utf16Example {public static void main(String[] args) {// BMP字符 '你'char bmpChar = '\u4F60'; // U+4F60System.out.println("BMP character: " + bmpChar);System.out.println("UTF-16 encoding (hex): " + Integer.toHexString(bmpChar));// 补充平面字符 😊String emoji = "\ud83d\ude0a"; // U+1F60ASystem.out.println("Supplementary character: " + emoji);for (int i = 0; i < emoji.length(); i++) {System.out.printf("UTF-16 encoding (hex): %04X\n", (int) emoji.charAt(i));}}
}
输出示例:
BMP character: 你
UTF-16 encoding (hex): 4F60
Supplementary character: 😊
UTF-16 encoding (hex): D83D
UTF-16 encoding (hex): DE0A
和UTF-8区别:
(3)、Base64
Base64是一种二进制到文本的编码方法,主要用于将任意二进制数据转换为ASCII字符串格式。它广泛应用于电子邮件附件、URL编码、HTTP基本认证等领域。
目的:
确保二进制数据能够在只支持文本的环境中安全传输,例如通过电子邮件或HTTP请求传递。
工作原理:
-
编码过程:Base64将每3个字节(24位)的二进制数据分成4组,每组6位,并将每个6位值映射到一个Base64字符表中的字符(共64个字符:A-Z, a-z, 0-9, +, /)。如果输入的数据不是3的倍数,则会在末尾添加填充字符=。
-
解码过程:将Base64编码的字符串还原为原始的二进制数据。
示例:
假设我们有一段二进制数据Hello。
import java.util.Base64;public class Base64Example {public static void main(String[] args) {String originalString = "Hello";// 使用Base64编码String encodedString = Base64.getEncoder().encodeToString(originalString.getBytes());System.out.println("Encoded with Base64: " + encodedString);// 使用Base64解码byte[] decodedBytes = Base64.getDecoder().decode(encodedString);String decodedString = new String(decodedBytes);System.out.println("Decoded from Base64: " + decodedString);}
}
输出示例:
Encoded with Base64: SGVsbG8=
Decoded from Base64: Hello
(4)、区别总结
(5)、具体应用场景
1、UTF-8
- 网页内容:大多数现代网页使用UTF-8编码来显示各种语言的文本。
- 文件存储:许多文本文件(如HTML、CSS、JavaScript文件)默认使用UTF-8编码。
2、UTF-16
- 编程语言内部表示:Java和C等编程语言使用UTF-16作为其字符串的内部表示。
- 数据库存储:某些数据库系统也支持UTF-16编码。
3、Base64
- 电子邮件附件:由于SMTP协议最初设计时并未考虑二进制数据的传输,因此Base64编码被广泛用于将附件转换为文本格式进行传输。
- URL编码:在URL中传递二进制数据时,Base64编码可以确保数据不会被误解为URL特殊字符。
- HTTP基本认证:用户名和密码在HTTP基本认证中通常使用Base64编码后传递。
(6)、示例代码对比
UTF-8和UTF-16编码示例:
import java.nio.charset.StandardCharsets;public class EncodingExample {public static void main(String[] args) {String originalString = "你好";// UTF-8 编码byte[] utf8Bytes = originalString.getBytes(StandardCharsets.UTF_8);System.out.println("Encoded with UTF-8:");printByteArray(utf8Bytes);// UTF-16 编码byte[] utf16Bytes = originalString.getBytes(StandardCharsets.UTF_16);System.out.println("Encoded with UTF-16:");printByteArray(utf16Bytes);}private static void printByteArray(byte[] bytes) {for (byte b : bytes) {System.out.printf("%02X ", b);}System.out.println();}
}
输出示例:
Encoded with UTF-8:
E4 BD A0 E5 A5 BD
Encoded with UTF-16:
FE FF 4F 60 59 7D
Base64编码示例:
import java.util.Base64;public class Base64Example {public static void main(String[] args) {String originalString = "Hello, World!";// 使用 Base64 编码String encodedString = Base64.getEncoder().encodeToString(originalString.getBytes());System.out.println("Encoded with Base64: " + encodedString);// 使用 Base64 解码byte[] decodedBytes = Base64.getDecoder().decode(encodedString);String decodedString = new String(decodedBytes);System.out.println("Decoded from Base64: " + decodedString);}
}
输出示例:
Encoded with Base64: SGVsbG8sIFdvcmxkIQ==
Decoded from Base64: Hello, World!
总结:
- UTF-8和UTF-16是用于将Unicode码点转换为字节序列的编码方式,适用于文本数据的存储和传输。UTF-8兼容ASCII,适合纯英文文本和多语言混合文本,而UTF-16主要用于编程语言内部表示和某些数据库系统。
- Base64是一种二进制到文本的编码方法,用于将任意二进制数据转换为ASCII字符串,以确保数据能够在只支持文本的环境中安全传输。它广泛应用于电子邮件附件、URL编码和HTTP基本认证等场景。
4、字符串和二进制转换
在计算机系统中,字符串转换为二进制(编码)和从二进制还原为字符串(解码)的过程是通过字符编码标准来实现的。常见的字符编码标准包括ASCII、UTF-8、UTF-16等。这些编码标准定义了如何将字符映射到二进制表示。
(1)、字符串转二进制(编码)
编码过程是将字符串中的每个字符转换为其对应的二进制表示。不同的字符编码标准有不同的规则。
例如:
- ASCII:每个字符用7位或8位表示(实际使用8位,其中一位通常为0)。
- UTF-8:可变长度编码,单字节字符用1字节表示,其他字符可能需要2到4字节。
- UTF-16:可变长度编码,基本多文种平面(BMP)中的字符用2字节表示,其他字符用4字节表示。(Java使用UTF-16编码来表示字符,char类型占用2字节,超出BMP的字符使用代理对表示。)
简单说明下:
对于字母‘A’,如果使用ASCII编码,仅会开一个字节的空间。如果使用UTF-8编码,也是会仅开辟一个字节的存储空间(UTF-8完全兼容ASCII码)。如果使用UTF-16编码,会开辟2个字节的空间来存储。
字符串转换为二进制的过程通常分为两个主要步骤:
1、根据编码方式将字符串转换为字节数组
- 字符串中的每个字符首先根据指定的编码方式(如UTF-8、UTF-16或ASCII)转换为相应的字节序列。不同的编码方式会生成不同长度和格式的字节数组。
2、将字节数组转换为二进制表示 - 每个字节可以进一步表示为一个8位的二进制数。因此,字节数组可以直接映射为一系列的二进制位。
代码示例:
import java.nio.charset.StandardCharsets;public class StringToBinaryExample {public static void main(String[] args) {// 原始字符串String originalString = "Hello, World!";// 使用 UTF-8 编码将字符串转换为字节数组(二进制)byte[] encodedBytes = originalString.getBytes(StandardCharsets.UTF_8);// 打印字节数组System.out.println("Encoded bytes (in hex):");for (byte b : encodedBytes) {System.out.printf("%02X ", b); // 16进制输出,X输出大写,x输出小写}System.out.println();// 可选:打印每个字节的二进制表示System.out.println("Encoded bytes (in binary):");for (byte b : encodedBytes) {System.out.printf("%8s ", Integer.toBinaryString(b & 0xFF));}System.out.println();}
}
输出示例:
Encoded bytes (in hex):
48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21
Encoded bytes (in binary):
01001000 01100101 01101100 01101100 01101111 00101100 00100000 01010111 01101111 01110010 01101100 01100100 00100001
解释:
原始字符串Hello, World!包含13个字符,且都是普通ASCII字符,所以在UTF-8编码后仅开辟了13个字节存储。
(2)、二进制还原为字符串(解码)
解码过程是将二进制数据转换回原始字符串。这需要知道原始字符串使用的字符编码标准(ASCII,UTF-8或UTF-16),以便正确地解释二进制数据。
以UTF-8为例说明:
在将二进制数据还原为字符串时,特别是使用UTF-8编码的情况下,确实需要特别注意其变长特性。UTF-8是一种变长编码格式,字符的长度可以从1到4字节不等。因此,解析UTF-8编码的二进制数据时,需要根据每个字节的前几位来判断该字符占用多少个字节。
步骤概述:
1、读取字节流:从二进制数据中逐字节读取。
2、识别字节类型。
原则:根据字节的前几位确定该字节是单字节字符还是多字节字符的一部分。
3、组合字节:对于多字节字符,按规则组合相应的字节以形成完整的字符。
4、转换为字符:将组合后的字节序列转换为对应的 Unicode 码点,再转换为字符。
说明下,识别为单字节还是多字节字符的具体规则如:
1、单字节字符
- 如果字节的第一位是0(即(b & 0x80) == 0),则该字节是一个单字节字符。
- 直接取8位二进制数转换成Unicode字符。
2、双字节字符 - 如果字节的前三位是110(即(b & 0xE0) == 0xC0),则该字节是一个双字节字符的开始。
- 组合当前字节和下一个字节,并将其转换为字符。即:取16位二进制数转换为Unicode字符。
3、三字节字符 - 如果字节的前四位是1110(即(b & 0xF0) == 0xE0),则该字节是一个三字节字符的开始。
- 组合当前字节及其后两个字节,并将其转换为字符。即:取24位二进制数转换为Unicode字符。
4、四字节字符 - 如果字节的前五位是11110(即(b & 0xF8) == 0xF0),则该字节是一个四字节字符的开始。
- 组合当前字节及其后三个字节,并将其转换为字符。即:取32位二进制数转换为Unicode字符。
解析原理代码示例:
import java.nio.charset.StandardCharsets;public class Utf8DecodeExample {public static void main(String[] args) {byte[] byteArray = { (byte) 0xE4, (byte) 0xBD, (byte) 0xA0, (byte) 0xE5, (byte) 0xA5, (byte) 0xBD, (byte) 0xF0, (byte) 0x9F, (byte) 0x98, (byte) 0x8A };StringBuilder decodedString = new StringBuilder();int i = 0;while (i < byteArray.length) {byte b = byteArray[i];if ((b & 0x80) == 0) {// 单字节字符 (0xxxxxxx)decodedString.append((char) b);i++;} else if ((b & 0xE0) == 0xC0) {// 双字节字符 (110xxxxx 10xxxxxx)int codePoint = ((b & 0x1F) << 6) | (byteArray[i + 1] & 0x3F);decodedString.append((char) codePoint);i += 2;} else if ((b & 0xF0) == 0xE0) {// 三字节字符 (1110xxxx 10xxxxxx 10xxxxxx)int codePoint = ((b & 0x0F) << 12) | ((byteArray[i + 1] & 0x3F) << 6) | (byteArray[i + 2] & 0x3F);decodedString.append((char) codePoint);i += 3;} else if ((b & 0xF8) == 0xF0) {// 四字节字符 (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)int codePoint = ((b & 0x07) << 18) | ((byteArray[i + 1] & 0x3F) << 12) | ((byteArray[i + 2] & 0x3F) << 6) | (byteArray[i + 3] & 0x3F);decodedString.append(Character.toChars(codePoint));i += 4;}}System.out.println("Decoded string: " + decodedString.toString());}
}
可以直接使用现成的方法new String()。
代码示例:
import java.nio.charset.StandardCharsets;public class BinaryToStringExample {public static void main(String[] args) {// 已编码的字节数组(假设这是从某个地方获取的二进制数据)byte[] encodedBytes = {72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33};// 使用 UTF-8 解码将字节数组转换回字符串String decodedString = new String(encodedBytes, StandardCharsets.UTF_8);// 打印还原后的字符串System.out.println("Decoded string: " + decodedString);}
}
输出示例:
Decoded string: Hello, World!
解释:
第一步编码我们打印%02X指定输出为十六进制数据,实际上十六进制的48就是十进制的72。
(3)、编码与解码的原理
1、字符编码
字符编码是将字符集中的字符映射到一组数字(通常是整数),然后进一步映射到二进制表示的过程。
编码过程:先将字符转字节数组,在将字节数组转二进制的过程。
常见的字符编码标准有:
- ASCII:仅支持128个字符,每个字符用7位表示(实际使用8位)。
- UTF-8:一种变长编码,兼容ASCII,单字节字符用1字节表示,其他字符可能需要2到4字节。
- UTF-16:另一种变长编码,基本多文种平面(BMP)中的字符用2字节表示,其他字符用4字节表示。
2、Java中的字符编码
在Java中,字符串是以Unicode格式存储的,具体来说是使用UTF-16编码。当你使用getBytes()方法时,你可以指定一个字符集(如UTF-8或UTF-16),该方法会根据指定的字符集将字符串转换为字节数组。
getBytes(Charset charset)方法:
- 参数:指定要使用的字符集(如StandardCharsets.UTF_8)。
- 返回值:返回一个字节数组,表示编码后的二进制数据。
new String(byte[] bytes, Charset charset)方法:
- 参数:
- bytes:包含二进制数据的字节数组。
- charset:指定要使用的字符集(如StandardCharsets.UTF_8)。
- 返回值:返回一个字符串,表示解码后的文本。
示例:处理非ASCII字符
import java.nio.charset.StandardCharsets;public class NonAsciiEncodingExample {public static void main(String[] args) {// 包含非ASCII字符的字符串String originalString = "你好,世界!";// 使用UTF-8编码将字符串转换为字节数组(二进制)byte[] encodedBytes = originalString.getBytes(StandardCharsets.UTF_8);// 打印字节数组System.out.println("Encoded bytes (in hex):");for (byte b : encodedBytes) {System.out.printf("%02X ", b); // 十六进制(4位)展示每个字节}System.out.println();// 可选:打印每个字节的二进制表示System.out.println("Encoded bytes (in binary):");for (byte b : encodedBytes) {System.out.printf("%8s ", Integer.toBinaryString(b & 0xFF)); // 二进制展示}System.out.println();}
}
输出示例:
Encoded bytes (in hex):
E4 BD A0 E5 A5 BD EF BC 8C E4 B8 96 E7 95 8C EF BC 81
Encoded bytes (in binary):
11100100 10111101 10100000 11100101 10100101 10111101 11101111 10111100 10101100 11100100 10111000 10010110 11100111 10010101 10001100 11101111 10111100 10100001
示例:解码非ASCII字符:
import java.nio.charset.StandardCharsets;public class NonAsciiDecodingExample {public static void main(String[] args) {// 已编码的字节数组(假设这是从某个地方获取的二进制数据)byte[] encodedBytes = { // 0x标识16进制的数(byte) 0xE4, (byte) 0xBD, (byte) 0xA0,(byte) 0xE5, (byte) 0xA5, (byte) 0xBD,(byte) 0xEF, (byte) 0xBC, (byte) 0x8C,(byte) 0xE4, (byte) 0xB8, (byte) 0x96,(byte) 0xE7, (byte) 0x95, (byte) 0x8C,(byte) 0xEF, (byte) 0xBC, (byte) 0x81};// 使用 UTF-8 解码将字节数组转换回字符串String decodedString = new String(encodedBytes, StandardCharsets.UTF_8);// 打印还原后的字符串System.out.println("Decoded string: " + decodedString);}
}
输出示例:
Decoded string: 你好,世界!
(4)、字符串和二进制转换总结
- 编码:将字符串转换为二进制数据的过程,涉及选择合适的字符编码标准(如UTF-8)。Java提供了getBytes(Charset charset)方法来进行编码操作。
- 解码:将二进制数据转换回字符串的过程,同样需要知道原始字符串使用的字符编码标准。Java提供了new String(byte[] bytes, Charset charset)方法来进行解码操作。
通过理解字符编码的基本原理和使用Java的内置方法,可以轻松地在字符串和二进制数据之间进行转换。这对于处理网络通信、文件存储等场景非常有用。
乘风破浪!Dare to Be!!!
相关文章:

消息队列篇--扩展篇--码表及编码解码(理解字符字节和二进制,了解ASCII和Unicode,了解UTF-8和UTF-16,了解字符和二进制等具体转化过程等)
1、理解字符,int,字节以及二进制存储 (1)、字符 字符是文本的基本单位,例如字母(A, B, C)、数字(1, 2, 3)、标点符号(!, ?, ,)以及其他符号&am…...

2024年度总结——理想的风,吹进现实
2024年悄然过去,留下了太多美好的回忆,不得不感慨一声时间过得真快啊!旧年风雪尽,新岁星河明。写下这篇博客,记录我独一无二的2024年。这一年,理想的风终于吹进现实! 如果用一句话总结这一年&am…...
代码工艺:实践 Spring Boot TDD 测试驱动开发
TDD 的核心理念是 “先写测试,再写功能”,其过程遵循一个严格的循环,即 Red-Green-Refactor: TDD 的流程 1. Red(编写失败的测试) 根据需求,先编写一个测试用例,描述期望的行为。…...

深度学习|表示学习|卷积神经网络|通道 channel 是什么?|05
如是我闻: 在卷积神经网络(CNN)中,channel(通道) 是指输入或输出数据的深度维度,通常用来表示输入或输出的特征类型。 通道的含义 输入通道(Input Channels):…...
PCDN的虚拟机与云主机区别
使用虚拟机和云主机运行PCDN(P2P CDN)时,主要存在以下区别: 一、资源分配与灵活性 虚拟机: 资源受限:虚拟机运行在物理服务器上,其资源(如CPU、内存、带宽)受到物理服务…...

计算机网络 (57)改进“尽最大努力交付”的服务
前言 计算机网络中的“尽最大努力交付”服务是网络层的一种数据传输方式。这种服务的特点是网络层只负责尽力将数据报从源端传输到目的端,而不保证数据传输的可靠性。 一、标记与分类 为数据分组打上标记: 给不同性质的分组打上不同的标记&#x…...
Redis 详解
简介 Redis 的全称是 Remote Dictionary Server,它是一个基于内存的 NoSQL(非关系型)数据库,数据以 键值对 存储,支持各种复杂的数据结构 为什么会出现 Redis? Redis 的出现是为了弥补传统数据库在高性能…...

如何解压rar格式文件?8种方法(Win/Mac/手机/网页端)
RAR 文件是一种常见的压缩文件格式,由尤金・罗谢尔(Eugene Roshal)开发,因其扩展名 “rar” 而得名。它通过特定算法将一个或多个文件、文件夹进行压缩,大幅减小存储空间,方便数据传输与备份。然而…...

网络仿真工具Core环境搭建
目录 安装依赖包 源码下载 Core安装 FAQ 下载源码TLS出错误 问题 解决方案 找不到dbus-launch 问题 解决方案 安装依赖包 调用以下命令安装依赖包 apt-get install -y ca-certificates git sudo wget tzdata libpcap-dev libpcre3-dev \ libprotobuf-dev libxml2-de…...

Coze插件开发之基于已有服务创建并上架到扣子商店
Coze插件开发之基于已有服务创建并上架到扣子商店 在应用开发中,需要调用各种插件,以快速进行开发。但有时需要调用的插件在扣子商店里没有,那怎么办呢? 今天就来带大家快速基于已有服务创建一个新的插件 简单来讲,就是…...

ORACLE-主备备-Failover
背景 随着业务的不断增涨,至使现有的单节点DG环境的连接已经无法满足当前业务需求,并且随着业务的重要性,同时也要求数据库的高可用性,减少数据库故障对业务的影响。于是规划迁移方案。 迁移方案如下: 因PRIMARY库本地磁盘空间已达到80%决定弃用,搭建高可用2个节点的RAC做…...

wampserver + phpstrom 调试配置
step 1 点击任务栏wampserver图标->php->php.ini[apache module] 在文件最后面,确保这些值被定义且跟以下的一样 xdebug.mode debug xdebug.start_with_request yes xdebug.client_port 9003 xdebug.client_host 127.0.0.1step 2 按如下配置 step3 下断点,运行即…...

Java Web-Cookie与Session
会话跟踪技术 会话跟踪技术是一种在 Web 应用程序中跟踪用户会话状态的机制,它允许服务器在多个请求之间识别和关联属于同一用户的请求,以便在整个会话过程中保持用户相关的信息。以下是几种常见的会话跟踪技术: Cookie 概念:Cook…...

Couchbase UI: Dashboard
以下是 Couchbase UI Dashboard 页面详细介绍,包括页面布局和功能说明,帮助你更好地理解和使用。 1. 首页(Overview) 功能:提供集群的整体健康状态和性能摘要 集群状态 节点健康状况:绿色(正…...
每日 Java 面试题分享【第 13 天】
欢迎来到每日 Java 面试题分享栏目! 订阅专栏,不错过每一天的练习 今日分享 3 道面试题目! 评论区复述一遍印象更深刻噢~ 目录 问题一:如何在 Java 中调用外部可执行程序或系统命令?问题二:如果一个线程…...

探究 Facebook 隐私安全发展方向,未来走向何方?
随着社交媒体的普及,隐私和数据安全问题成为了全球关注的焦点。Facebook,作为全球最大的社交平台之一,其隐私安全问题尤其引人注目。近年来,随着用户数据泄露事件的不断发生,Facebook 不断调整其隐私政策,探…...

第三十一周学习周报
目录 摘要Abstract文献阅读总体架构实验分析 知识复习总结 摘要 在本周阅读的文献中,作者提出了一种基于生成对抗网络(GAN)和长短期记忆网络(LSTM)融合模型的连续管钻井参数预测方法,旨在提高连续管钻井的…...

白嫖一个可以公网访问、带评论和图床的博客系统
这里我来把搭建这个网站的过程记录下,可供新手朋友搭建 完成github page的创建 首先先打开github官网,然后打开your repositories这个标签 然后新建一个repositories,名字是比较特殊的,为<username>.github.io这个格式&am…...
定时器、计数器
定时器:TON TOF TONR:保持型接通定时器 TP:脉冲定时器:触发一次,就开始计时 TP:按下I0.1 TP开始计时,Q电开始有电,时间到Q点失电 计数器:CTU加 CTD减 CTUD加减 两个方法…...
Ubuntu Server连接wifi
背景 家里服务器放在客厅太吵了, 准备挪到阳台, 所以买了TP wifi接收器, 因此需要配置wifi连接. 刚开始买了Tenda Ax300, 结果不支持服务器系统, 买前还是得和客服交流交流. 准备 驱动安装 对于windows系统来说, 这款接收器是免驱的, 但在linux上需要安装相应型号驱动 安装…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...