消息队列篇--扩展篇--码表及编码解码(理解字符字节和二进制,了解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上需要安装相应型号驱动 安装…...

关于MySQL InnoDB存储引擎的一些认识
文章目录 一、存储引擎1.MySQL中执行一条SQL语句的过程是怎样的?1.1 MySQL的存储引擎有哪些?1.2 MyIsam和InnoDB有什么区别? 2.MySQL表的结构是什么?2.1 行结构是什么样呢?2.1.1 NULL列表?2.1.2 char和varc…...

深入剖析SpringBoot启动机制:run()方法详尽解读
摘要 本文深入解析SpringBoot的启动机制,以run()方法为核心,逐步追踪并详细解释其关键步骤。首先探讨run()方法的工作原理,然后深入代码层面分析各个关键环节。文章提供刷新后钩子和启动后任务的代码示例,帮助读者理解SpringBoot源…...

Nginx中部署多个前端项目
1,准备前端项目 tlias系统的前端资源 外卖项目的前端资源 2,nginx里面的html文件夹中新建,tlias和sky两个文件夹。 切记这是在nginx/html下创建的 mkdir sky mkdir tlias 把tlias和sky的资源都放到对应的文件夹中 3,编辑配置ngi…...

1688寻源通:赋能跨境贸易的高效业务平台
前言 在全球化的浪潮下,跨境电商已成为推动经济发展的重要力量。作为国内领先的B2B电商平台,1688凭借其强大的供应链资源和创新技术,推出了“寻源通”业务,旨在帮助国内供应商和跨境采购商实现更高效、更精准的供需匹配ÿ…...

JVM深入学习(一)
目录 一.JVM概述 1.1 为什么要学jvm? 1.2 jvm的作用 1.3 jvm内部构造 二.JVM类加载 2.1类加载过程 2.2类加载器 2.3类加载器的分类 2.4双亲委派机制 三.运行时数据区 堆空间区域划分(堆) 为什么分区(代)?(…...

Qt Creator 15.0.0如何更换主题和字体
1.打开Qt Creator 15.0.0 (Community), 2.点击编辑栏3.点击Preferences... 4.修改主题,点击环境,修改Theme:栏 5.修改字体大小,点击文本编辑器,修改字号栏。,修改Theme:栏...

“大模型横扫千军”背后的大数据挖掘--浅谈MapReduce
文章目录 O 背景知识1 数据挖掘2 邦费罗尼原则3 TF.IDF4 哈希函数5 分布式文件系统 一、MapReduce基本介绍1. Map 任务2. 按键分组3. Reduce 任务4. 节点失效处理5.小测验:在一个大型语料库上有100个map任务和若干reduce任务: 二、基于MapReduce的基本运…...

shallowRef和shallowReactive的用法以及使用场景和ref和reactive的区别
Vue3 浅层响应式 API 1. ref vs shallowRef 1.1 基本概念 ref: 深层响应式,会递归地将对象的所有属性转换为响应式shallowRef: 浅层响应式,只有 .value 的改变会触发更新,不会递归转换对象的属性 1.2 使用对比 // ref 示例 const deepRe…...

maven、npm、pip、yum官方镜像修改文档
文章目录 Maven阿里云网易华为腾讯云 Npm淘宝腾讯云 pip清华源阿里中科大华科 Yum 由于各博客繁杂,本文旨在记录各常见镜像官网,及其配置文档。常用镜像及配置可评论后加入 Maven 阿里云 官方文档 setting.xml <mirror><id>aliyunmaven&l…...

HTML5+SVG+CSS3实现雪中点亮的圣诞树动画效果源码
源码介绍 这是一款基于HTML5SVGCSS3实现雪中点亮的圣诞树动画效果源码。画面中的圣诞树矗立在雪地中,天上飘落着雪花。当鼠标滑过圣诞树时,可见到圣诞树上的灯光闪烁,同时左下角探出雪怪模样的半个脑袋,四处张望着。整体画面栩栩…...