Java字符串及字符在JVM内部是什么编码 ?
Java字符串(String类)在内存中统一采用UTF-16编码存储,每个字符占用2字节,对应Unicode基本多文种平面(BMP)的字符。Java字符类型(char)基于Unicode字符集设计,UTF-16是其具体编码实现方案。
Java字符串及字符与UTF-8编码的关系是什么 ?
UTF-8 也是Unicode的一种实现方式,区别在于它的字节结构(字节组织形式)有自己的格式。如,一个汉字的范围是0X4E00到0x9FA5,是指unicode的值,至于放在utf-8的编码里去就是由三个字节来组织,所以可以看出unicode是给出一个字符的范围,定义了这个字是码值是多少,至于具体的实现方式可以多种多样,可以是UTF-8,也可以是UTF-16;
UTF-8:英文字符占用一个字节,汉文字符占用三个字节;UTF-16:英文字符、汉文字符都占用两个字节,其中汉字以[-2, -1]开始。
I/O操作(文件读写、网络传输)需显式指定字符集(如UTF-8、GBK)进行编码转换,否则使用平台默认编码(通过Charset.defaultCharset()查看)进行字节转换,I/O操作时未显式指定编码可能导致乱码,因平台默认编码可能与UTF-16不一致(如Windows默认GBK):
String text = "文本内容"; // java字符串,底层采用UTF-16编码存储
byte[] bytes = text.getBytes(StandardCharsets.UTF_8); // 转换为UTF-8字节数组,用于I/O操作
Java字符串转码样例
/// java字符串编码 --> UTF-8编码:%E5%A4%9A%E6%99%AE%E5%8B%92.pdf %是每个字节间的分隔符
String encodedFileName = java.net.URLEncoder.encode("多普勒.pdf", "UTF-8");
/// UTF-8编码 --> java字符串编码:多普勒.pdf
String decodedFileName = java.net.URLDecoder.decode(encodedFileName, "UTF-8");
/// 229, 164, 154
short i1 = 0xE5, i2 = 0xA4, i3 = 0x9A;
System.out.println(i1); System.out.println(i2); System.out.println(i3);
/// idea中默认的字符串编码为UTF-8, 更改编码方式:settings->fileCoding->GlobalEncoding = GBK
System.out.println("默认编码格式:" + System.getProperty("file.encoding"));
/// java获取系统中默认的编码UTF-8【应该是默认的转码方式】
System.out.println("默认编码格式:" + Charset.defaultCharset().name());
/// [-27, -92, -102, -26, -103, -82, -27, -117, -110, 46, 112, 100, 102] 多普勒.pdf
byte[] bytes = decodedFileName.getBytes();
System.out.print("字节数组(默认编码):" + Arrays.toString(bytes));
decodedFileName = new String(bytes, Charset.defaultCharset().name());
System.out.println(decodedFileName);
/// [-27, -92, -102, -26, -103, -82, -27, -117, -110, 46, 112, 100, 102] 多普勒.pdf
/// 这里说明:229和-27的存储都是【11100101】,229是无符号整数的解码,-27是有符号整数的解码
bytes = decodedFileName.getBytes(StandardCharsets.UTF_8);
System.out.print("字节数组(UTF-8编码):" + Arrays.toString(bytes));
decodedFileName = new String(bytes, StandardCharsets.UTF_8);
System.out.println(decodedFileName);
/// [-2, -1, 89, 26, 102, 110, 82, -46, 0, 46, 0, 112, 0, 100, 0, 102] 多普勒.pdf
// 多:[-2, -1, 89, 26],普:[-2, -1, 102, 110],勒:[-2, -1, 82, -46]
bytes = decodedFileName.getBytes(StandardCharsets.UTF_16);
System.out.println("字节数组(UTF-16编码):" + Arrays.toString(bytes));
decodedFileName = new String(bytes, StandardCharsets.UTF_16);
System.out.println(decodedFileName);
/// [63, 63, 63, 46, 112, 100, 102] ???.pdf
bytes = decodedFileName.getBytes(StandardCharsets.ISO_8859_1);
System.out.print("字节数组(ISO_8859_1编码):" + Arrays.toString(bytes));
decodedFileName = new String(bytes, StandardCharsets.ISO_8859_1);
System.out.println(decodedFileName);