JAVA里字符编码的探索与理解

开发 后端
今天终于把JAVA里一个比较头痛的问题——字符编码弄清晰了,所以写一篇文章来纪念一下,也为大家提供一点自己的心得。

今天终于把JAVA里一个比较头痛的问题——字符编码弄清晰了,所以写一篇文章来纪念一下,也为大家提供一点自己的心得。

众所周知,JAVA为了国际通用,用的是UNICODE来保存里面的字符。而UNICODE只是一个种字符集,字符的存储和表示要用到一定的字符编码格式,而与UNICODE对应的字符编码格式就是我们常看到的UTF-8,UTF-16等等,而UTF-8是最常用的,所以人们常常把它和UNICODE等同起来(我以前就是这样的),这在某些情况下是没有错的,但这样的理解在JAVA里就会产生一些混淆。我们用下面的程序来演示一下。

定义一个字符串

String name = "堂";

这个字符串就一个字符,把它取出来

char c_name = name.charAt(0);

JAVA里的char型是十六位的(两个字节),但是如果是用UTF-8的话可能会不只两位(UTF-8是变长存储的),那看来JAVA本身并不是用UTF-8来保存的,口说无凭,做个实验吧。

首先看看char里保存的内容  

 

int low = (c_name) & 0xff;//取c_name的低位
  int high = (c_name >> 8) & 0xff;//取c_name的高位
  System.out.println(Integer.toHexString(high) + " " + Integer.toHexString(low));

  

结果是58 02

只有两个字节而已(16位),那么真正的UTF-8编码的内容是什么呢,再看看吧。

为了方便,我写了一个辅助方法printbyte,作用是把一个byte数组的每个元素按照十六进制格式打印出来,同样为了方便,我把它作为静态方法。 

 

#p#

 public static void printbyte(byte[] bt)
  {
  for (int i = 0; i < bt.length; i++)
  {
  int hex = (int)bt[i] & 0xff;
  System.out.print(Integer.toHexString(hex) + " ");
  }
  System.out.println(" length = "+bt.length);
  }
  byte[] utf_8 = name.getBytes("utf-8");
  printbyte(utf_8);

 

结果是e5 a0 82 length = 3

哇,三个字节!看来JAVA内部用的真不是UTF-8,那用的是什么呢?UTF-16?看一下便知。  

byte[] utf_16 = name.getBytes("utf-16");
  printbyte(utf_16);

 

结果是fe ff 58 02 length = 4,靠,四个字节了。咦?后面的低16位不正是和开始c_name的十六进制表示一样的吗?看来JAVA真正的内部字符编码和UTF-16有或多或少的联系。JAVA内部究竟是用的什么字符编码呢?这个问题我也找了很久,后来在THINK IN JAVA 3rd的12章里看到一个例子出现了UTF-16BE,难道是它?  

byte[] utf_16be = name.getBytes("utf-16be");
  printbyte(utf_16be);
  结果出来了:58 02 length = 2

 

哈哈,I got it!不多不少两个字节,内容也一样。果然是它。同时我在里面也看到,UNICODE的编码还有一个LE,这里的BE,LE我想应该是bigendian和littleendian吧。

【编辑推荐】

  1. 如何在PHP中使用正则表达式
  2. Java正则表达式应用详解
  3. Java正则表达式初学者使用法简介
责任编辑:庞桂玉 来源: CSDN
相关推荐

2018-01-22 17:02:48

Python字符编码ASCII

2009-12-24 17:16:23

Ado Oledb

2022-02-15 10:11:18

二进制汇编代码函数调用

2011-12-16 16:02:42

Java

2011-04-07 16:23:09

Web网页设计编码

2024-03-04 11:10:01

2009-06-08 19:52:47

Eclipse字符编码

2015-05-14 15:38:40

javajava内存泄露

2011-11-17 13:59:41

Java内存管理内存泄露

2022-05-18 10:56:58

Java字符串编码

2023-04-13 00:24:00

前端编码JavaScrip

2010-10-08 09:51:52

Mysql设置字符

2023-11-08 09:49:19

Java实践

2023-11-30 09:45:38

Java工具

2010-03-12 08:55:06

Java内省反射

2017-09-23 15:28:32

JavaOptional方法

2009-06-16 11:32:00

Java泛型

2018-02-26 16:07:48

Android3DDepth

2009-06-11 17:31:27

Java泛型

2016-05-31 10:11:51

点赞
收藏

51CTO技术栈公众号