字符集与编码
术语
字符(character)是具有语义值的文本的最小单位。
字符集(character set)是可能由多种语言使用的字符的集合。例:拉丁语字符集由英语和大多数欧洲语言使用,但希腊语字符集仅由希腊语使用。
编码字符集(coded character set)是一个字符集,其中每个字符对应于一个唯一的数字。
一个编码字符集的编码点(code point)是字符集中或编码空间中允许的任何值。
编码空间(code space)是一个整数范围,其值为编码点。
编码单元(code unit)是一个位序列,用于在给定的编码表单中对库的每个字符进行编码。有的文档中称之为编码值(code value)。
编码单元例子:US-ASCII: 7 bits,UTF-8, GB18030: 8 bits,UTF-16: 16 bits,UTF-32: 32 bits
字符串"abc"
包括4个字符,4个编码点:
(1) UTF-32编码时: 4个编码单元,00000061, 00000062, 00000063, 00010400
(2) UTF-16编码时: 5个编码单元,0061, 0062, 0063, d801, dc00
(3) UTF-8编码时: 7个编码单元,61, 62, 63, f0, 90, 90, 80
编码格式区别
Unicode、GB2312都是编码字符集,即一个编号(数字)到字符的一种映射关系,仅仅是一种映射关系。
GBK、UTF-8都是编码格式。GBK和UTF-8都是用来序列化或存储Unicode编码的数据的,但是分别是2种不同的格式。除了格式不一样之外,他们所关心的unicode编码范围也不一样,UTF-8考虑了很多种不同国家的字符,涵盖整个Unicode码表,所以其存储一个字符的编码的时候,使用的字节长度也从1字节到4字节不等;而GBK只考虑中文(在Unicode中的一小部分字符的编码),所以它算好了只要2个字节就能涵盖到绝大多数常用中文(2个字节能表示6w多种字符),所以它存储一个字符的时候,所用的字节长度是固定的。
Java中的编码
首先Java的String使用的编码是Unicode,但是当String存在于内存中时(也就是当程序运行时,你在代码中用String类型的引用对它进行操作时,也就是String没有被存在文件中且也没有在网络中传输(序列化)时),是“只有编码而没有编码格式的”,所以Java程序中的任何String对象,说它是GBK还是UTF-8都是错的。GBK和UTF-8是编码格式而不是编码,String在内存中不需要“编码格式”(记住编码格式是在存文件或序列化的时候使用的), 它只是一个Unicode的字符串而已。
所以Java里面String是不带编码格式的,而String.toByteArray(String charsetName)
得到的byteArray
是带编码格式的,格式就是你传入的charsetName
,我们不妨把toByteArray
的这个过程叫做编码;另外,new String(byte bytes[], String charsetName)
是把一个byte数组(带编码格式)以charsetName指定的编码格式翻译为一个不带编码格式的String对象,我们不妨把这个过程叫解码。
String(byte[] bytes)
通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
String(byte[] bytes, Charset charset)
通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
byte[] getBytes()
使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte数组中。
byte[] getBytes(Charset charset)
使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
public class Test { public static void main(String[] args) throws UnsupportedEncodingException { String str1; String str2; byte[] bytes; str1 = "你好"; bytes = str1.getBytes("UTF-8"); // 用UTF-8编码序列化到字节数组中 str2 = new String(bytes, "UTF-8"); // 使用UTF-8方式解码 System.out.println(str2 + "123"); bytes = str1.getBytes("GBK"); str2 = new String(bytes, "GBK"); System.out.println(str2 + "123"); bytes = str1.getBytes("UTF-8"); str2 = new String(bytes, "GBK"); System.out.println(str2 + "123"); // UTF-8编码,GBK解码 str1 = "浣犲ソ"; // 这是"你好"的GBK编码的字符串 str2 = new String(str1.getBytes("GBK"), "UTF-8"); System.out.println(str2 + "123"); } } // 输出: // 你好123 // 你好123 // 浣犲ソ123 // 你好123
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具